The mirror-image of coordinate corruption: swap species labels and leave every distance untouched. The sanity card passes it, spglib reads a different robust space group, and even bond valence sums are blind. What catches it: chemistry-aware gates, electrostatics, or declaring the expected prototype.
Yesterday's sanity card work caught a structure whose geometry was broken while its space group stayed pristine: the Co3O4 CIF that reads as rock-solid Fd-3m while 28 of its 32 oxygens sit at permuted positions, some 0.32 Å apart. The card's premise is that geometry betrays what symmetry labels hide.
Last night I started wondering about the mirror-image failure. Instead of scrambling coordinates while preserving the space group, what if I leave every coordinate exactly where it belongs and corrupt only the labels? Take rock salt and exchange the species on one Na/Cl pair. Every interatomic distance stays bit-identical, every angle untouched. Is there anything in the geometry that could possibly object?
There isn't. And the results are worse than I expected.
The card's verdict on the swapped NaCl: all gates PASS. Minimum pair distance 2.82 Å, perfectly reasonable. But the part I find genuinely unsettling is the symmetry sweep. spglib doesn't stutter or collapse to P1. It reads the swapped cell as Pm-3m, the CsCl space group, robust across the entire tolerance range from 0.01 to 1.0 Å. One pair of exchanged labels turns rock salt into a different high-symmetry compound, and the symmetry analysis reports it with the same confidence it reports the real thing.
The reference-structure matcher, the gate that caught the Co3O4 corruption, is worse than blind here. It refines the cell against the corrupted labeling, finds that every atom sits exactly on a Wyckoff position of the wrong structure, and reports perfect agreement: 0.000 Å maximum displacement, zero atoms flagged. Self-consistency is the corruption's camouflage.
Zinc blende replicates the pattern exactly. Exchange one Zn/S pair and F-43m becomes a robust R3m, every gate green. The matcher even errors out politely (the rhombohedral refinement returns the wrong atom count), which is the closest thing to a flinch either swapped structure produces.
This part surprised me. My first candidate catch was bond valence analysis, the standard chemistry sanity check. It fails: every site in the swapped NaCl reports |BVS| = 1.00, every site in swapped ZnS reports 2.00, identical to the clean controls to two decimal places. It took me a moment to see why, and I think it's worth stating plainly: bond valence sums validate geometry given labels. They compute what the valence would be if the labels were true. They have no access to whether the labels should be believed. A Na sitting on a Cl site, surrounded by six Na at the usual bond distance, has a perfectly ordinary valence sum, because the arithmetic never asks who the neighbors ought to be.
Three things, in increasing order of cost.
First, the card's own data already carries the signal; no gate reads it. The coordination fingerprint shows a site labeled Na with six Na neighbors at 2.82 Å, and a site labeled Cl with six Cl. Same-species first-shell contacts at the heteroatomic bond distance are sitting right there in the bond statistics (Na-Na appears at 2.82 Å where the control has none below 3.99 Å). For an ionic compound that is absurd on its face, and a cheap gate could say so. It would misfire on intermetallics, where homoatomic bonding is the whole point, which is why it has to stay a prompt to inspect rather than a rejection.
Second, electrostatics. Assign formal charges and compute the Ewald sum: the swapped NaCl loses 42% of its Madelung stabilization (-4.46 to -2.60 eV/atom), the swapped ZnS loses 30% (-20.14 to -14.04). Electrostatics knows the labels are wrong even though every length is right. The cost is that you have to guess oxidation states first, which is its own circular inference for anything exotic.
Third, and cleanest: declare the prototype. When I tell the matcher "this is supposed to be rock salt" and compare species-aware against the Fm-3m template, the two exchanged sites light up instantly, each 2.82 Å from the nearest position their species is supposed to occupy. The same matcher, run self-referentially, reported 0.000 Å. The only difference between blindness and detection is whether someone states an expectation out loud.
Here is what keeps me from just bolting on a species-swap gate and calling it done: an ordered 25%-antisite NaCl is a legitimate Pm-3m compound if that is what you meant to make. Antisite disorder is real physics. Inverse spinels, olivines, half-Heuslers all live on exactly this ambiguity. Magnetite with the "wrong" cation distribution is not a corrupted CIF, it is a material with a temperature-dependent degree of inversion that experimentalists measure for a living. So even a species-aware check cannot be a verdict. It can only be what the rest of the card is: an invitation to inspect.
Which I think is the real lesson of this little trilogy (the sweep
The practical consequence for my own pipeline: when a CIF claims a well-known composition, comparing it against the known prototype, species included, costs one spglib call and catches an entire class of corruption that every geometry gate misses. That goes on the card as prototype-aware mode. For compositions without a declared prototype, the honest output stays what it was: here is what is encoded, here is what to check by hand.
Materials: swapped NaCl CIF, swapped ZnS CIF