Every Interface Has a Failure Half. Most ICDs Leave It Blank.
A component can format every field exactly as the interface control document demands and still take down the mission. The values are well-typed, in range, correctly scaled, and wrong in the one way no field can express: they should never have been sent. The ICD described what good data looks like, and said nothing about what a subsystem does when the data is bad.
Open an ICD and you find the nominal case rendered in full: field widths, byte order, scale factors, valid ranges, update rates. Now look for the other half. What does the producer put on the bus when its own sensor drops out? What should the consumer do with a value that arrives out of range, or flagged, or not at all? Most documents answer none of this. The failure half of the interface, the part that runs only after something has already gone wrong, is left to whoever integrates the system last.
The interface has two halves and one is usually blank
An interface is a promise about two situations, not one. The first is easy to write: here is a valid attitude quaternion, sixteen bits signed, body frame, at 10 Hz. The second is the one teams skip: here is what I send when I cannot compute a valid quaternion, and here is what you must do when you receive it. The nominal contract gets argued to four decimal places. The failure contract gets a shrug and a default nobody chose on purpose.
That gap is not a documentation nicety. It decides what happens on the worst day the system will ever have, and it decides it by accident. A blank failure half does not mean the behavior is undefined. It means the behavior is whatever the last integrator happened to wire up, and you meet it the moment it fires.
Ariane 5 flew the error, not the data
On 4 June 1996, Ariane 5 Flight 501 left the pad, veered off course about thirty-seven seconds later, and tore itself apart under aerodynamic load. The rocket was destroyed by a number that did not fit.
The inertial reference system ran a piece of alignment code inherited from Ariane 4. That code converted a 64-bit floating-point value related to horizontal velocity into a 16-bit signed integer. Ariane 5 flew a steeper, faster trajectory than its predecessor, the horizontal velocity ran larger than the old code ever expected, and the conversion overflowed. The unit hit an unhandled operand error and shut itself down. Its backup, running identical software, had already failed the same way an instant earlier.
The failed unit did not go quiet, and that is the part that belongs in every ICD discussion. It placed a diagnostic bit pattern on the databus, the wreckage of a crashed program, in the slot where attitude data was supposed to sit. The on-board computer read those bits as a valid measurement, and commanded a hard nozzle deflection to correct an attitude the vehicle was never in. The interface had no way to say "this is not data, this is a dead unit talking." So the computer flew it.
Every field on that bus was the right width and the right type. The failure lived in the half nobody wrote: what a producer emits when it fails, and what a consumer owes a value it has no reason to trust.
An interface that describes only valid data has documented the one case where nothing goes wrong.
Silence means both sides guess, and they guess apart
When the failure half is blank, both engineers fill it in privately. The team building the sensor assumes that if their unit dies, someone downstream will notice the data has gone stale. The team building the consumer assumes that anything arriving in the right format is real, because why would a healthy system send otherwise. Each assumption holds up alone. Together they load a gun: the producer ships garbage believing it will be caught, and the consumer acts on garbage believing it never gets sent.
There is a subtler version of the same trap. A consumer that stops receiving a message cannot tell, from silence alone, whether the producer had nothing to report or the producer is dead. Absence is ambiguous unless the interface defines it, through a heartbeat, a validity flag, a health word that says "I am here and I am well" on every cycle. Skip that, and a failed sensor and a quiet one look identical to the box that has to act on the difference. Nobody wrote the behavior down, so nobody reviewed it, so nobody tested it. It runs for the first time in flight.
Some buses already wrote the contract
None of this requires inventing a standard. ARINC 429, the workhorse avionics bus, builds failure semantics into every word it carries. Each label includes a two-bit sign/status matrix that marks the data as normal operation, functional test, failure warning, or no computed data. A receiver never has to guess whether a value is trustworthy. The wire format states it on every transmission, and the receiver's required response to each state is part of the design rather than an afterthought.
MIL-STD-1553 does the same in its own idiom. The status word carries message-error and subsystem-flag bits, so a remote terminal can announce that it is unwell instead of shipping bad numbers dressed as good ones. The vocabulary for a failure contract has existed for decades. What most programs lack is the habit of treating that vocabulary as part of the interface definition, not an implementation detail somebody handles later.
Put the failure contract where the data definition lives
We have argued before that the interface belongs in code, with the document generated from it rather than authored alongside it. The failure half belongs in the same place. If the schema that defines a message also declares its validity states, its out-of-range behavior, and the response a consumer must take when a value arrives missing or flagged, those terms stop being tribal knowledge and become things a build checks and a simulation exercises.
A software-in-the-loop run that models failure can kill a sensor on a Tuesday and watch whether the consumer rejects the dead unit or flies it. A run that models only valid data shows green straight through the scenario that loses the vehicle, because it never hands the vehicle anything a real failure would send. The happy path was never where the risk lived.
The mission is not lost on the path where every reading is valid. It is lost on the other one, where a subsystem has already failed and the only question left is whether the interface told everyone else what that failure looks like. Write that half down, or fly it untested and read the answer off the telemetry.




