The fastest way to turn a temporary Microsoft 365 problem into a public incident is to overwrite yesterday’s valid file with today’s empty one. I have seen jobs authenticate correctly, receive valid JSON, and still produce unusable output because a list was renamed, permissions changed, or an upstream query returned zero rows.
The problem: the job assumes new data is better data
A directory export might usually contain hundreds of Banner IDs, names, email addresses, and profile URLs. If it suddenly contains three records, that is probably not a successful update.
$summary = [
'previousCount' => 842,
'sourceCount' => 3,
'validCount' => 3
];
The quirk: valid XML or JSON can still be destructive
Schema validation proves that a file is shaped correctly. It does not prove that the data is reasonable. I add a minimum-count or percentage-change rule before replacing anything.
$minimumExpected = 500;
$maximumDrop = 0.25;
$drop = 1 - ($sourceCount / max($previousCount, 1));
if ($sourceCount < $minimumExpected || $drop > $maximumDrop) {
alertAdmin("Directory export aborted: suspicious source count");
exit('Previous valid file preserved');
}
The workaround: write, validate, then swap
$temporary = $outputPath . '.tmp';
file_put_contents($temporary, $xml);
if (!validateXml($temporary)) {
unlink($temporary);
throw new RuntimeException('Generated XML failed validation');
}
rename($temporary, $outputPath);
The rename is the quiet hero here. Consumers see either the old complete file or the new complete file—never a half-written file. I treat a missing optional phone number as a warning, but a missing Banner ID or account identifier as fatal because identity matching becomes unreliable.
