DEV Community

Solon Framework
Solon Framework

Posted on

How Solon Turns Exceptions into HTTP Status Codes (400/404/405/415)

You've deployed a Solon service and, at 2 a.m., a client starts sending malformed requests. Your endpoint answers with 400 Bad Request. A few minutes later someone calls a URL that doesn't exist — 404 Not Found. Then a colleague posts JSON to an endpoint that only accepts application/x-www-form-urlencoded415 Unsupported Media Type.

You grep your codebase for "Not Found" and "Unsupported Media Type" and find nothing. That's normal: you're not supposed to write those. Solon's built-in StatusException converts unhandled client-caused errors into HTTP status responses automatically. Knowing this exception hierarchy will save you a late night — and it's a neat look at how the framework thinks about failures.

The exception family tree

Solon's exceptions form two small trees. Everything framework-level descends from SolonException (provided by the solon module); the distributed world has its own root, CloudException (provided by solon.cloud):

SolonException                            (solon — the framework root)
└── StatusException                       (solon — client-caused errors, v2.8.3+)
    ├── AuthException                     (solon-security-auth)
    ├── ValidatorException                (solon-security-validation)
    └── CloudStatusException              (solon-cloud)

CloudException                            (solon.cloud — the distributed root)
├── CloudConfigException                  (distributed config service)
├── CloudEventException                   (distributed event service)
├── CloudFileException                    (distributed file service)
└── CloudJobException                     (distributed job service)
Enter fullscreen mode Exit fullscreen mode

StatusException: the one behind your 4xx

StatusException (available since v2.8.3) is a "status exception", and the official docs define its purpose precisely: it represents handling exceptions caused by the client side — as opposed to bugs or server-side failures. It carries a code (the HTTP status code) and a message (a description).

The key mechanism: when this exception is not handled, it is automatically converted into an HTTP status response. That's why a bare 404 pops out of your service even though you never wrote a line for it.

The framework itself throws it in four built-in places:

When What Solon throws
Multipart parsing fails new StatusException("Bad Request", e, 400)
No route path record matches new StatusException("Not Found", 404)
No route path method record matches new StatusException("Method Not Allowed", 405)
No Consumes match new StatusException("Unsupported Media Type", 415)

So the four most common 4xx codes in a Solon app — 400, 404, 405, 415 — are all produced by this one class, from four well-defined routing/parsing checks. When you see one of them, don't hunt for where it's thrown in your code; check why the request didn't match instead.

Three derived exceptions

Three more exceptions extend StatusException, each from a different module, each with its own extra members:

Exception Module What it signals Extra members
AuthException solon-security-auth Authentication/authorization failed code, status
ValidatorException solon-security-validation Parameter validation failed code, annotation, result
CloudStatusException solon-cloud A cloud component reported a status problem code

These are the "typed" versions you'll actually catch in business code: wrap a service call, catch AuthException, and you know the caller wasn't authenticated without inspecting the message text.

CloudException: the distributed family

When your app runs in distributed mode, errors from the cloud layer come from a separate root — CloudException, the base of the solon.cloud world:

Exception What it signals
CloudConfigException Distributed config service error
CloudEventException Distributed event service error
CloudFileException Distributed file service error
CloudJobException Distributed job service error

If a Cloud*Exception shows up, the fault is almost always in the distributed component (config center, event bus, file store, job scheduler), not in your request handling — a useful first guess when triaging.

A mental model for debugging 4xx

Put together, the mapping is small enough to keep in your head:

  • 400 / 404 / 405 / 415 → client-side problem; check the request format, path, HTTP method, and Content-Type against your route definitions (these are the four built-in StatusException usages).
  • AuthException → authentication/authorization layer (solon-security-auth).
  • ValidatorException → parameter validation (solon-security-validation) — inspect the annotation and result members for details.
  • Cloud*Exception → distributed component failure (solon.cloud family).
  • Anything else extending SolonException → your own business exceptions; catch them where you'd normally handle domain errors.

Why the code matters

StatusException exists because, before v2.8.3, dealing with 400/404/405 required more manual work. Introducing a status-carrying exception (and auto-converting it to a response) gave the framework — and you — one consistent way to signal "the client got it wrong" all the way from routing internals to security/validation modules and cloud components. One pattern, one root, one mental model.

The full official description lives in the Solon docs — exception relationships (Solon v4.0.4).

Top comments (0)