One field, three different envelopes, and a fix that made it worse
The same subscription-status field came back nested two levels deep, one level deep, or bare at the top, depending on account state. My fix didn't catch that. It added math on top of a check that was already wrong.
By Meet ModiA subscription-status field came back from the backend in three different shapes depending on account state. Sometimes nested two levels deep inside the response object. Sometimes one level deep. Sometimes sitting bare at the top level with nothing wrapping it.
Frontend code written against one specific shape worked for some accounts and silently read as nothing for others, no error, no crash, just a falsy value where a boolean should have been.
The bug: half the checks were reading a field that wasn't there. The fix that shipped didn't check that. It added more logic on top of the missing field instead.
Take 1: the fix that made it worse
The working theory was that the boolean field itself was untrustworthy, so someone added an explicit expiration-date comparison on top of it, reasoning that a date comparison would be a stronger signal than a flag that might be stale.
function isSubscriptionActive(response: any) {
const status = response.data?.subscription?.isActive;
const expiresAt = response.data?.subscription?.expiresAt; // ms timestamp
const now = Date.now();
// extra safety: don't trust the flag alone
return status && expiresAt * now > now;
}expiresAt * now is nonsense, a timestamp multiplied against another timestamp produces a number with no relationship to either, and it made it into review because the surrounding code looked deliberate and the tests happened to cover only accounts where status was already false, so the broken multiplication never got exercised. It shipped, made the false-negative rate worse overnight, and got reverted the next day.
The bigger issue wasn't the arithmetic bug, though that alone earned the revert. It's that response.data.subscription.isActive was the wrong path for a chunk of accounts before this change even landed. Layering a broken date check on top of an already-wrong boolean read produces two bugs stacked on each other, and fixing the top one doesn't touch the bottom one.
Take 2: check you're reading the field at all
Before adding any new logic, I went back to where the three response shapes actually came from. Some account states returned the field nested inside data.subscription, some inside just data, some with the field sitting bare at the top of the response with no wrapper at all.
function getSubscriptionStatus(response: any): boolean {
const candidates = [
response?.data?.subscription?.isActive,
response?.data?.isActive,
response?.isActive,
];
const match = candidates.find((v) => typeof v === 'boolean');
return match ?? false;
}The selector checks each known shape in order and uses whichever one is actually a boolean. No date math, no extra distrust of the backend's own flag, just reading the field from wherever it actually lives for that response. Once the boolean is being read correctly, it turns out to be trustworthy on its own.
The date-comparison logic in take 1 was solving a problem that didn't exist. The flag wasn't unreliable. It was unread.
What I should have done first
I should have logged the raw response shape for a sample of failing accounts before writing any fix. Instead the first fix was reasoned from a theory (the flag is untrustworthy) rather than from data (the flag isn't where the code is looking), and it took a broken deploy to force the actual investigation that should have come first. Distrust the data path before you distrust the data.
More Posts
The vector database was innocent
I built a RAG service over the OpenTelemetry docs, then pointed OpenTelemetry back at it to find out why answers took 16 seconds. It wasn't the LLM. It wasn't the vector search either.
A query that returned nothing nested inside it
The exact same logical query returned full nested data through the REST layer and empty shells through the service layer underneath it. Same fields requested. Same backend. One shorthand parameter that only one of the two actually understood.
The redirect that forgot where you were going
A user clicked a link straight to a class recordings page. Their session had expired. They logged back in and landed on the dashboard home instead, three clicks away from where they started.