Debugging Production API Failures by Reading the Client's Error, Not the Server's Logs
TIL that when a mobile app reports 'network error' against a production API, the fastest path to the actual cause is the client-side error object, not tailing server logs that show nothing wrong.
The Problem #
A driver reported the app couldn't load orders. Server logs showed the API healthy, responding normally to every request it received — because it never received this driver's requests at all. I spent the first chunk of debugging time looking in the wrong place.
Context #
The instinct when "the API is broken" is to go straight to server logs, which is right when the server actually received the request and wrong when it didn't.
What I Tried #
Reproduced against the production API from my own device, which worked fine, and concluded (wrongly, in hindsight) that it must be that specific driver's device or network.
What Went Wrong #
"Works on my device" ruled out the server but didn't actually diagnose anything — it just moved the mystery from "why is the API broken" to "why is this one device broken," without new information to work from.
The Solution #
Had the driver read back the actual error, not just "it doesn't work" — React Native's fetch/network errors carry a specific message (TypeError: Network request failed, or on Android, sometimes an UnknownHostException surfaced through the bridge). That specific error was the actual diagnostic signal, and it pointed at DNS resolution, not the API itself.
try {
await fetch(API_URL);
} catch (err) {
// err.message here was the whole story — don't just log "upload failed"
console.error("Network error:", err.message);
}Why It Works #
A generic "it doesn't work" report is compatible with dozens of causes; the actual thrown error narrows that down immediately, because React Native's networking layer is specific about why a request failed, not just that it failed. Server logs can only tell you about requests that arrived — they're the wrong source of truth for a request that never made it there.
Lessons Learned #
"Reproduce it myself" is a good instinct but not a substitute for the actual error message from the failing device — my own network conditions (DNS, connectivity) aren't the same as a driver's, and "works for me" rules out fewer causes than it feels like it does.
What I Would Do Differently #
I'd add a step to the bug-report flow that surfaces the raw error message to the user (or logs it remotely), instead of relying on a verbal "it's not working" description as the primary diagnostic input.
Related Concepts #
Client-side vs. server-side error visibility, React Native network error types, remote error logging.
Related content
Understanding UnknownHostException in Android (and Why the API 'Worked Locally')
TIL that an Android UnknownHostException on a hostname that resolved fine everywhere else usually isn't a DNS problem at all — it's the app pointed at a hostname that only ever existed on my dev machine.
Debugging Problems That Only Appear in Production
TIL that a bug I couldn't reproduce locally turned out to depend on a real difference between environments — request concurrency — that my local setup structurally couldn't produce, no matter how hard I tried to repro it.
Debugging a MongoDB/WiredTiger Cache Pressure Issue in Production
TIL that intermittent MongoDB slowdowns that don't show up in query logs can be a WiredTiger cache eviction problem, not a query problem — and the fix was a resource limit, not an index.