The Robustness Principle, aka Postel’s Law: be conservative in what you send, be liberal in what you accept. Coined by Jon Postel in an early TCP spec — your code should produce output that strictly conforms to the spec, but tolerate input that deviates from it as long as the intent is still clear.
A more formal restatement: be contravariant in the input type, covariant in the output type — accept the broadest reasonable set of inputs, return the narrowest, most predictable set of outputs.
Where it shows up
- Parsers and deserializers that ignore unknown fields rather than rejecting the whole payload
- APIs that accept multiple equivalent representations of the same value (e.g. case-insensitive headers)
- Network protocols designed to keep working even when peers send malformed or unexpected packets
The case against it
The principle has aged less well than I’d have guessed:
- Tolerance entrenches bugs. If your parser silently accepts a malformed message, every other implementation now has to replicate that tolerance to stay interoperable — “bug for bug compatible.” Martin Thomson’s argument (2015–2018 IETF drafts) is that this makes systems less robust over time, not more.
- It can be a security hole. Being liberal about what you accept means accepting more attack surface. Rochet & Pereira (2018) showed this exact leniency exploited in Tor’s onion routing to deanonymize clients.
- It defers pain rather than removing it. Marshall Rose’s take: a sloppy implementation works fine until, years later, it meets a strict one and breaks in a way that’s hard to trace back to the original violation.
My read: still a reasonable default for systems you don’t control both ends of, but worth pairing with explicit validation/logging at the boundary so “liberal acceptance” doesn’t quietly become “no idea what’s actually flowing through this system.”
See also
- SOLID — Liskov Substitution covers similar contravariant/covariant ground at the type level
- Good Software Practices