Some bugs are loud and obvious. Others sit quietly in a codebase doing exactly what the code says, which isn't quite what anyone intended. The quiet ones are the more interesting category, because finding them is closer to archaeology than debugging. A UI banner that wouldn't clear is the same shape of bug on the front end. These are its data-side cousins.
The currency display bug
In travel booking systems, taxes are complicated. There are base fares, carrier-imposed fees, and government taxes, each with its own rules about which currency it should display in. Domestic US travel adds specific airport facility charges and segment taxes with their own currency handling.
The bug was that these taxes showed up with the wrong currency symbol. The amounts were right and the calculation was fine. What wasn't being carried through to the display layer was the currency context. In the exchange flow, where an agent is repricing a ticket change and quoting the tax breakdown to a customer, that's exactly the kind of error that erodes confidence in the tool. The agent can't be sure which values to trust.
Fixing it meant tracing how those tax line items were assembled for rendering and making sure the right currency followed them through the pipeline. The root cause was a missing currency association at the point where the values were gathered into the display model. The fix itself was small once I found it. Tracing it was the bulk of the work, as usual.
The feature flag that didn't exist
The subtler one corrected a feature flag reference in the pricing details service: a flag name that had been sitting in the code but had never actually been created in the feature flagging service.
Every time the code evaluated that flag, it got a "not found" response, which the SDK treated as "off". Whatever the flag was meant to enable was never reachable. It wasn't failing loudly or throwing errors. It was silently defaulting to disabled, no matter what anyone had configured.
Flag names are strings. Nothing checks a flag name at compile time against what's registered in your flagging service. Create a flag under a slightly different name than the one in the code, and the mismatch is invisible, at build time and at runtime, unless you go looking for it. Removing flags that have outlived their purpose is its own discipline. This is the opposite failure: a flag that was never really there.
The passenger type that was never resolved
A third bug of the same quiet kind. The exchange fare search service generates fare options when a traveller changes a booked ticket, and that calculation depends on the passenger type (adult, child, infant, various discount categories) because each attracts different fares and tax treatment.
The fare generation helper was receiving a passenger type code, a short string like ADT or CHD, but it wasn't performing the lookup that translates that code into the full passenger type definition from the reference data service. For standard adult passengers it probably held up, because the code was making assumptions that happened to be true for the common case. For less common categories, the missing lookup produced wrong results without failing loudly. The fix was to resolve every code through the reference data before fare generation runs.
This is the kind of bug that's easy to wave through in review. The code looks plausible, the variable names suggest the right thing is happening, and the tests probably only cover the common cases. The tell is usually spotting that a code path receives something that looks like an identifier and treats it as if it were the thing itself.
Config drift and why it stays hidden
The flag and the passenger type are the same broader problem: drift. The code and the thing it references, a flag registry or a reference dataset, fall out of sync, and because neither side fails in a detectable way, the drift sticks around. The only symptom is behaviour that's quietly wrong, which is easy to blame on something else or miss entirely.
You usually find these by poking around a nearby area and noticing the mismatch. Validating that references resolve at startup is one mitigation. A naming convention and a clear "create it before you reference it" habit is usually more practical. The loud bugs get fixed because they announce themselves. The quiet ones only get fixed if someone goes looking.