NORAD IDs Passed 99,999. Here's What Broke.
The satellite catalogue outgrew a five-digit field this year. Our catalogue code did not get the memo, and the failure showed up as a wrong diagnosis from a guard that was doing its job.
For sixty-odd years, every object in the public satellite catalogue has had a number that fits in five digits. The two-line element format was designed around that. Columns three through seven of each line hold the catalogue number, and there is no room on either side.
This year the catalogue crossed 100,000. The numbers kept being issued, the format did not grow, and the reconciliation is a scheme called Alpha-5: the first of the five characters becomes a letter. A is 10, B is 11, and so on up to Z for 33, skipping I and O because they look like digits. So the object numbered 100,000 is written A0000, and the scheme runs out at Z9999, which is 339,999. That buys the format a few more years.
We knew about Alpha-5. We had read about it. We had not actually handled it, and last week that caught up with us.
The symptom
A customer reported that planning kept failing on a satellite with a recent element set. The failure came from the stale-elements guard we added in August, and the message said the elements were stale and quoted an altitude of nan km.
The epoch on those elements was thirteen days old. Not stale. And an altitude of not-a-number is not what staleness looks like. Staleness looks like a satellite below the surface, a real number that is simply wrong.
The cause
Our catalogue does not store two-line element sets as text. It stores the fields, and it rebuilds the two lines when something asks for them. The rebuild had a line in it that zero-padded the catalogue number to five characters.
For a six-digit number, that produced six characters. The line came out seventy columns wide instead of sixty-nine. Every field after the catalogue number was shifted one column right. SGP4 does not parse by field name. It parses by column. So it read the wrong digits as the epoch and the mean motion and everything else, and did what you would expect with garbage in: it produced not-a-number out.
The guard caught the result. It just explained it wrong, because when we wrote it the only way we had ever seen a bad altitude was staleness.
Line 1 of a two-line element set, three ways. The first is the classic layout. The second is the one we were producing for numbers above 99,999, one column too wide. The third is Alpha-5, with the leading letter standing in for the first two digits. The grid is the letter mapping; I and O are skipped.
The fix
Three parts.
Encoding. When the catalogue rebuilds a line for a number above 99,999, it now emits the Alpha-5 form. Letter for the first two digits, four digits after it, five characters total, sixty-nine columns.
Decoding. When we ingest elements, a leading letter in the catalogue number field is decoded back to the integer. We had been getting away without this because our upstream had been quietly serving us the integer in a separate field, which is exactly why the rebuild bug sat there unnoticed.
Diagnosis. The guard now distinguishes between elements it could not parse and elements it could parse but which propagate somewhere implausible. The first is reported as a parse failure with the offending line. The second is still reported as stale. They are different problems with different fixes, and the message should say which one you have.
And tests with catalogue numbers on both sides of the boundary, which is the part that is slightly embarrassing to have been missing.
The lesson
Fixed-width formats fail at the boundary, and the boundary is always further away than anyone will be around to care about, until it is not. The two-line element format was a good design in the 1970s. The people maintaining it today did the sensible thing with Alpha-5, and the fix on our side was an afternoon. The expensive part was the week in which a correct refusal carried an incorrect reason, and a customer spent time investigating staleness that did not exist.
If you parse two-line elements anywhere in your stack, go look at how you handle the catalogue number field. By the end of September several hundred objects in the public catalogue already carried six-digit numbers, and that count only goes up.