skip to content

Error Handling & Problem Responses

How a thrown failure becomes a response: the central exception-to-status mapper, one shared failure body, the fallback when nothing catches it. Probed because a leaked stack trace is the red flag.

on this pageshow

explore

questions

24

In a server-side web framework, what response does a request whose URL matches no registered route receive, and what produces it?

level: juniorimportance: must knowfreq 74%

answer

  1. nobody registered that path
  2. someone still has to answer
  3. the framework answers, not your code
  4. built-in fallback emits 404
  5. page or structured body by configuration

basics

~20 s

The framework's own fallback answers with 404 Not Found, and no handler of yours runs. Routing finds no match, so the request falls through to the built-in default error response, rendered as a page or as a structured body.

solid answer

~50 s

Routing is a lookup: if no registered route matches the request, there is no handler to invoke, yet the connection still needs an answer. Every server-side framework therefore keeps a fallback layer that runs when nothing produced a response, and for an unmatched path it emits `404 Not Found`. That response is framework code, not application code - you did not write it, and no breakpoint in your handlers will be hit. Its representation varies: some frameworks render a built-in HTML page, some emit a small structured body, some choose between them from the request's `Accept` header, and some return the status line with an empty body. How much detail it carries depends on whether the framework is running in its development or its production mode. You replace it by registering your own last-resort handler at the outermost layer, keeping the `404` status.

go deeper

for a junior

Recall that an unregistered path produces 404 from the framework itself, with no handler running. Be able to say the response is built in rather than something you wrote.

for a middle

Explain the fall-through: routing finds no candidate, the fallback layer answers, and the representation depends on the framework's default and on whether that fallback negotiates.

for a senior

Show that you first establish which layer emitted a 404 in production - gateway, static-file layer, framework fallback or a catch-all route - before changing any configuration.

for a principal

Discuss whether unmatched-path responses should look identical across services, and where that uniformity is enforced, weighing a shared default against per-team freedom.

A request that names a path nobody registered is not an error in your code - there is simply no code to run. The framework still owes the client a response, and the layer that supplies it is the **default fallback**: the answer of last resort that runs when no handler produced anything. ## What "no route matched" actually means Routing is a lookup from the request (its path, usually together with its method) to a registered handler. Three outcomes are possible: - a handler is found and runs - the normal path; - a handler is found, runs, and fails - the failure path, where mapping and handlers get a chance; - **no handler is found at all** - nothing in the application has been asked to produce a response. Only the third case is the unmatched-route fallback. It is worth separating from a superficially identical case: a handler that runs, looks something up, finds nothing, and deliberately returns `404`. On the wire the two look the same; inside the process they come from completely different layers, which is why changing your fallback's format sometimes changes only half the 404s a client sees. ## The fallback is framework code, not your code The important mental model for a junior interview is that the framework has an answer prepared for the case where you have none. It is registered before your application starts, it sits at the outermost layer of request handling, and it runs without consulting your routes. Practical consequences: 1. Adding a handler for a *similar* path does not affect it - routers do not do nearest-match; a miss is a miss. 2. Logging inside handlers will not show the request, because no handler ran; the framework's own request log will. 3. The body you see is a framework artifact. If it does not look like your API's errors, that is the reason. ## What the body looks like | Fallback style | Typical body | Typical `Content-Type` | Who it suits | |---|---|---|---| | Built-in page | Rendered HTML naming the status | `text/html` | A person in a browser | | Built-in structured body | Small object with status and message | `application/json` | Programmatic clients | | Negotiated | Page or structured body chosen from `Accept` | Either | Mixed audiences | | Status only | Empty | None or omitted | Minimal or proxy-fronted services | Frameworks differ here: some ship a page by default and keep it even for clients that asked for data, others default to a structured body, and others negotiate. This is the single most common surprise for teams building an API - handled errors come back as data because your code serialised them, while the unmatched-route response comes back as markup because the framework's fallback rendered it. The amount of detail is a separate axis from the representation. In a development mode the fallback may list registered routes or echo request details to help you spot the typo; in a production mode the same fallback prints a short message. That switch is worth knowing exists, because it is the default that leaks. ## Which layer actually produced the 404 you are holding In a deployed system, more than one component can emit `404`, and they are easy to confuse: - a **proxy or gateway** in front of the application, for a path it was never told to forward; - a **static-file layer**, for a file path under a served directory that does not exist; - the **framework fallback**, for a request that reached the application and matched no route; - **your own catch-all route or handler**, if you registered one. Cheap ways to tell them apart: look for an access-log line for that exact request inside the application (absent means something in front answered); compare the body and headers with what the application emits elsewhere; and check for headers or a body style the application never produces. ## Overriding it Replacing the built-in answer is normally three decisions: 1. **Register a last-resort handler at the outermost layer**, so it sees requests the router rejected rather than sitting inside a route group the request never entered. 2. **Choose the representation** - most teams settle on one machine-readable shape for every failure so a client parses one thing. 3. **Keep the status** `404`. The fallback's job is presentation, not re-classification; turning an unmatched path into `200` or `500` misinforms caches, clients and your own dashboards. ## What an interviewer is listening for That you can say "the router found nothing, so the framework's built-in fallback answered", that you do not believe a catch-all route is required for 404 to happen, and that you know the default body is a framework choice you can replace rather than a fixed property of HTTP.

  • A handler runs, finds no record and returns 404 - is that the same mechanism?
    No. That is a handled response: your code chose the status and the body, so the fallback never runs. The two are indistinguishable on the wire but come from different layers, which matters the day you change the fallback's format and only unmatched-path responses change shape.
  • Why might an API client get HTML for an unknown URL while handled errors arrive as data?
    Handled errors go through your code's serialisation; the unmatched-path response goes through the framework's fallback, which may render its built-in page regardless of `Accept` unless you override it or enable negotiation on the fallback itself.
  • Does registering a catch-all route replace the fallback?
    Effectively yes for paths it covers: once a route matches, the request is handled and the fallback never runs. The risk is coverage - a catch-all bound inside a route group or prefix only shadows requests that reach it, leaving the built-in fallback answering everything else.

saying these in an interview costs you the question

  • Thinks you must add a catch-all route or no 404 happens at all
  • Assumes every 404 a client sees was produced by application code
  • Believes the default 404 body is always structured data for API clients
  • Confuses an unmatched route with a handler that found no record
  • Treats the built-in error page as safe to leave exposed in production
open as a page

In a server-side web framework, what does a central exception-to-status handler registry do, and why prefer it to per-route catches?

level: juniorimportance: must knowfreq 74%

basics

~20 s

A central registry maps failure types to HTTP statuses in one place: the framework catches whatever a handler throws, looks up the closest registered type, and runs that mapper to build the response. Route code stays free of transport concerns.

open as a page

Why can a web framework's error mapper not turn a failure into a 500 once the response has been committed?

level: middleimportance: must knowfreq 58%

basics

~20 s

Once the status line and headers are flushed to the socket, nothing can retract them; HTTP has no take-back. A mapper running afterwards can only append to the body, emit a trailer, log the failure, or abort the connection.

open as a page

In a web framework, why does the default error response show a stack trace in development but a terse message in production?

level: middleimportance: must knowfreq 66%

basics

~20 s

Two rendering modes of one fallback, chosen by a flag, not by the failure. Development mode prints the failure type, message and stack for the author; production mode prints a status and short message so internals never reach untrusted callers.

open as a page

When two registered exception handlers could both catch a thrown failure, how does a web framework choose which one runs?

level: middleimportance: must knowfreq 63%

basics

~20 s

Most frameworks resolve by specificity: they walk the thrown type's ancestry and pick the nearest registered ancestor, so a subtype registration beats a base-type one. Where the registry is a scanned list of predicates, the first match wins and registration order decides.

open as a page

In a web framework, why should every failure response be built by one shared factory rather than by each handler?

level: middleimportance: must knowfreq 62%

basics

~20 s

A single factory is the only place that can guarantee every failure leaves with the same fields, a correlation id and no internal detail. Per-handler bodies drift as soon as a second person adds an endpoint under time pressure.

open as a page

In a server-side web framework, in what order do authentication, authorization and existence checks normally run?

level: middleimportance: must knowfreq 62%

basics

~20 s

Authentication runs first in a pre-handler stage, authorization next, existence last inside the handler after the lookup. The earliest stage to refuse writes the response, so an anonymous request for a missing record answers 401, not 404.

open as a page

After a catch-all handler was registered on the broadest failure type, a service returns 500 where it used to return 404 — why, and how do you fix it?

level: seniorimportance: must knowfreq 57%

basics

~20 s

The catch-all is now the nearest registered ancestor for failures the framework raises itself, which already carried their own status. Instead of reaching the built-in mapping, they hit the catch-all and become 500. Fix by narrowing it or honouring a carried status.

open as a page

Your handlers all return one failure body, yet an unmatched route or an unparsable request body returns a different shape. Why, and what fixes it?

level: seniorimportance: must knowfreq 55%

basics

~20 s

Those failures are raised before handler invocation, so no handler code runs and the framework renders its own built-in body. Fix it by attaching the framework's central failure hook to the same factory, wrapping pre-handler failures like thrown ones.

open as a page

When the shared failure factory is handed a thrown exception, what should it put in the client-facing message field?

level: seniorimportance: must knowfreq 52%

basics

~20 s

Text chosen from the mapped error code, not the exception's own message. The factory should default to a generic message for anything unrecognised, and send the exception text and stack to the log record keyed by the same correlation id.

open as a page

If you answer 404 rather than 403 to hide a record's existence, at which pipeline stage must that decision be made?

level: seniorimportance: must knowfreq 48%

basics

~20 s

Make it where both facts are known: in the handler, after the record loads and the visibility rule runs. A pre-handler hook cannot mask what it never loaded, and rewriting every refusal into 404 over-masks failures unrelated to hidden records.

open as a page

On an API where every route requires a credential, does a request to an unregistered path answer 401 or not-found?

level: juniorimportance: should knowfreq 42%

basics

~20 s

It depends where the credential check is mounted. Mounted globally, ahead of route resolution, it answers 401 for any path; attached per route, it never runs for an unregistered path and the built-in not-found response wins.

open as a page

In a web framework, what is returned by default when a request's path matches a route but its method does not?

level: middleimportance: should knowfreq 50%

basics

~20 s

Most frameworks answer 405 Method Not Allowed, because the router can see the path is registered under other methods. Some answer 404 instead, either because method and path form one lookup key or to avoid confirming that the path exists.

open as a page

In a framework offering both route-scoped and global exception handlers, how do the two interact, and what does rethrowing from a handler do?

level: middleimportance: should knowfreq 52%

basics

~20 s

Scopes nest: the innermost registry that covers the failing route is consulted first, and a failure with no match there falls through outward to the global one. Rethrowing from a mapper typically resumes that outward fall-through.

open as a page

Should a shared failure-body factory take the correlation id as a parameter or read it from request-scoped context?

level: middleimportance: should knowfreq 44%

basics

~20 s

Read it from request-scoped context. A parameter works but puts the burden back on every call site, which is the drift the factory exists to remove. The factory must also define what it does when that context is empty.

open as a page

Should request validation run before or after authorization in a web framework's pipeline, and what does each order give away?

level: middleimportance: should knowfreq 50%

basics

~20 s

Authorize first for anything a stranger can reach. A validation error returned before the rights check hands an unauthorized caller your field names, accepted values and sometimes which identifiers exist; validating first only buys a friendlier error.

open as a page

A streaming endpoint fails halfway through a body whose 200 status was already sent — how should the server end that response?

level: seniorimportance: should knowfreq 48%

basics

~20 s

Do not end it cleanly. Abort so the body stops short of its declared length or terminator — the one incompleteness a receiver can detect — and record the failure server-side. A trailer or agreed end marker is extra.

open as a page

How would you make failures that happen after a response is committed visible in production, given they never reach the error mapper?

level: seniorimportance: should knowfreq 44%

basics

~20 s

Stop relying on response status: the committed status is what gets recorded, so a half-sent success logs as a success. Emit a dedicated counter, mark the record post-commit, and set a correlation header before the first flush.

open as a page

When a service installs a custom fallback, why do some clients still receive a built-in error page or an opaque proxy error?

level: seniorimportance: should knowfreq 47%

basics

~20 s

A custom fallback covers only failures that reach the framework. Requests rejected by a proxy in front or by the host server's parser, and failures raised inside the fallback itself, are answered by a different layer.

open as a page

How would you decide which endpoints buffer their response fully and which stream, given that buffering keeps failures mappable?

level: principalimportance: should knowfreq 38%

basics

~10 s

Treat it as buying error fidelity with memory. Buffer anything small and bounded so late failures still map to a real status; stream only where size or duration forces it, under a completeness contract.

open as a page

How would you decide whether exception-to-status mapping lives in one central registry or in per-module handlers across a large service?

level: principalimportance: should knowfreq 43%

basics

~20 s

Centralise the vocabulary, distribute the membership. Define a small shared set of failure categories with one status each in a central registry, and let each module map its own failure types onto those categories rather than onto statuses directly.

open as a page

How do you keep one internal failure contract when two surfaces of the same service must serialize errors in different wire formats?

level: principalimportance: should knowfreq 34%

basics

~20 s

Split the failure value from its rendering. One factory produces a format-agnostic failure value; a renderer chosen per surface serializes it into that surface's standard. Handlers raise failures and never learn which surface they are serving.

open as a page

How would you keep failure precedence uniform across an edge gateway and dozens of independently built backend services?

level: principalimportance: should knowfreq 33%

basics

~20 s

Write the order down as a contract - credential, then rights, then existence - settle credentials once at a shared edge, and verify every endpoint against it. The one service that answers differently becomes the enumeration oracle.

open as a page

How would you set and enforce a default error-fallback policy across many services so failures stay debuggable without leaking internals?

level: principalimportance: nice to knowfreq 38%

basics

~20 s

Decide one baseline - terse by default, detail only on explicit opt-in, full failure in the log - then make it an inherited default rather than a rule teams must remember, and verify it by probing every deployed environment.

open as a page