Learn how to handle web errors and logging in Clojure applications, including exception mapping, structured logs, request correlation, and avoiding information leakage in HTTP responses.
Web error handling: The practice of turning application and infrastructure failures into predictable HTTP responses without hiding useful operational evidence or leaking sensitive internals.
In a Clojure web application, the real goal is not “never throw.” The goal is to map failures cleanly at the web boundary. Clients should get stable HTTP semantics. Operators should get enough structured logging and correlation data to debug the issue. Those are related goals, but they are not identical.
Good web error design distinguishes between:
These categories should not all collapse into the same 500 response or the same vague log line. A validation failure, a permission denial, and a database outage deserve different response and logging behavior.
That distinction is easier to maintain when the application already has a clear error vocabulary. Domain error values, explicit exception types, or stable error codes make the web boundary far less ad hoc.
A common failure mode is translating the same error at several layers:
That creates duplicate noise and contradictory behavior. Usually the web layer should have one clear place where exceptions or domain errors become HTTP responses.
One useful pattern is a boundary layer that translates exceptions or domain error values into stable HTTP responses:
1(defn error-response [status code message]
2 {:status status
3 :headers {"content-type" "application/json"}
4 :body {:error {:code code
5 :message message}}})
The goal is not to serialize every stack trace. The goal is to keep the client contract stable while preserving richer evidence in logs and monitoring systems.
Stable error codes help here because they let the team connect:
Structured logs matter because web traffic is high-volume and repetitive. Useful fields often include:
Without those fields, web logs become difficult to aggregate or correlate under production load.
Severity discipline matters too. If every handled validation miss is logged like an outage, the signal collapses. Operationally useful logging distinguishes expected client failures from genuinely abnormal infrastructure or application faults.
Web logs become far more useful when they include stable fields such as:
This makes it much easier to correlate a failing client request with the corresponding server-side evidence.
One of the best web-operability habits is attaching a request ID early and carrying it through:
Without correlation IDs, the logging story becomes much noisier as the application grows.
Many systems log the same failure three or four times because each layer is “being safe.” Usually one authoritative log entry with strong context is better than several noisy ones with weaker context.
The same principle applies to exception handling. Catching at many layers often produces duplicated stack traces with less context each time. One good log event at the right layer usually beats four mediocre ones.
A common web mistake is returning too much detail when something goes wrong:
Those details can be useful in logs, but they should not usually be exposed in client-visible error payloads.
This is especially important in mixed HTML and API systems where a stack trace intended for debugging can leak into a JSON or HTML response unexpectedly.
HTML and JSON boundaries may also need different user-facing error behavior even when the operational evidence is shared. A browser page might redirect or render an error view. An API client usually needs a stable error payload instead.
This area goes bad when:
500A clean design usually logs once at the right boundary and keeps the client-visible message appropriately limited.
If clients must parse English prose to decide what happened, the boundary is too loose. Stable codes and stable status semantics make the system easier to evolve.
Translate failures at the HTTP boundary. Keep response contracts predictable. Log structured context with request correlation. Expose enough to help clients react correctly, but keep operational and security-sensitive detail in the server-side evidence stream instead of the response body.