Skip to content

Unknown-Field Handling Rule

Forward-compatibility rule — instantiates Asymmetric Interface Tolerance Calibration

Fixes in advance what a receiver does with fields it doesn't recognize — ignore, preserve, or reject — so tomorrow's additions don't break today's readers.

Of all the ways an input can be "unexpected," one is special: a field the receiver has simply never heard of, usually because the sender is newer. Unknown-Field Handling Rule is the narrow, decisive policy for exactly that case — it pre-commits the receiver to ignore, preserve-and-pass-through, or reject anything it doesn't recognize. Its defining move is to resolve the single most common forward-compatibility ambiguity before it arises and in one place, so an interface can evolve — new fields added by newer producers — without every existing reader treating the unfamiliar as an error. It is a small rule that decides whether the whole ecosystem is upgrade-tolerant or upgrade-brittle.

Example

A mobile app talks to a backend that ships new features weekly, while users update the app on their own lazy schedule — so at any moment millions of older app versions are receiving JSON built by a newer server. Sooner or later that server adds a field: loyalty_tier. The unknown-field handling rule decides what a two-versions-old app does when it sees it. Under a must-ignore rule[1] the old app skips the field it doesn't understand and renders the screen fine; the feature simply lies dormant until the app updates. Under a naïve "reject unexpected keys" rule, the same addition would crash every older client the moment the server deployed — turning a routine, additive change into an outage. The rule is chosen once, applied by every reader, and it is the difference between a backend that can evolve freely and one held hostage by its oldest client.

How it works

  • Classify, then apply one verdict. Anything the schema doesn't name is "unknown," and the rule assigns it a single fixed disposition — ignore, preserve, or reject — rather than leaving each parser to improvise.
  • Ignore for pure consumers. A reader that only uses data drops what it doesn't understand and proceeds, so additive changes are non-breaking by construction.
  • Preserve for intermediaries. A relay, proxy, or store-and-forward node passes unknown fields through untouched, so it doesn't silently strip data meant for a downstream party.
  • Reject only where unknown means unsafe. In a strict or security-sensitive context an unrecognized field is treated as a violation, on the theory that anything unaccounted-for could be an attack or an error.

Tuning parameters

  • Default disposition — ignore vs preserve vs reject as the baseline. Ignore maximizes forward compatibility; reject maximizes strictness; preserve protects data in transit.
  • Ignore vs. preserve — whether "not understood" means discard or carry through untouched. The distinction is invisible until something downstream needed the field you dropped.
  • Ambiguity ceiling — how many unknowns (or what fraction of a payload) is tolerated before the input is treated as malformed rather than merely newer — the budget past which "unfamiliar" becomes "suspect."
  • Round-trip guarantee — whether a reader that re-emits a record must reproduce the unknown fields it preserved, so passing through an old node doesn't quietly strip newer data.
  • Context sensitivity — whether the disposition varies by field location (unknown top-level key vs unknown enum value vs unknown nested object), since each carries different risk.

When it helps, and when it misleads

Its strength is that it is the cheapest possible enabler of independent evolution: with a must-ignore rule in place, producers can add fields whenever they like knowing no conforming reader will break, which is what lets the two sides of an interface version on separate schedules. It converts the scariest routine change — adding to a payload — into a safe one.

Its failure modes come from choosing the wrong disposition for the role. A pure ignore rule at an intermediary silently strips fields the next hop needed, corrupting data no one sees go missing. A reject rule where ignore belonged makes the interface gratuitously upgrade-brittle. And "ignore unknown fields" can be a genuine security hole where an unrecognized field is exactly how something smuggles past validation — so the rule must not be applied blindly across a trust boundary. Its classic misuse is being set once as "ignore everything" and never revisited, so the receiver quietly tolerates unbounded junk and loses any signal that a producer has gone off the rails. The discipline is to pick the disposition per role — consumer, relay, or guard — and to cap tolerated unknowns rather than accept them without limit.

How it implements the components

  • normalization_and_repair_boundary — the ignore / preserve / reject choice is a repair-boundary decision for one class of irregularity: it sets whether an unrecognized field is dropped, carried, or refused.
  • ambiguity_budget — the rule caps how much unrecognized content counts as tolerable "newer producer" before the input is treated as malformed, spending a bounded allowance for the unknown.

It governs only the unknown-field case, not the whole accept envelope (that's Tolerant Reader / Strict Writer Policy), not general canonicalization of known-but-messy input (Lenient Parser with Canonicalizer), and not agreeing versions up front (that's Version Negotiation or Capability Probe).

Notes

The gap between ignore and preserve is the one people get wrong. A pure consumer can safely drop what it doesn't understand, but any node that forwards or re-serializes data must preserve unknown fields, or it silently deletes information meant for someone downstream — a data-loss bug that is invisible precisely because nothing errors. Decide the disposition by what the receiver does with the record, not by how strict you feel.

References

[1] Must-ignore — a rule, common in extensible-format and protocol specifications, requiring a receiver to silently skip elements it does not recognize rather than fail. It is the convention that makes additive change forward-compatible; its counterpart must-understand marks the fields a receiver may not ignore.