Error Codes and Error Semantics
Plumego does not define a global error code system.
This is deliberate.
Instead of enforcing a one-size-fits-all error model,
Plumego defines where error semantics live and where they must not leak.
This document clarifies:
- Which errors Plumego itself may generate
- Which errors must be defined by applications
- How HTTP status codes relate to errors
- What “error codes” mean in a Plumego system
First Principle: Errors Are Semantic, Not Numeric
In Plumego:
Errors represent meaning, not numbers.
Numeric error codes (if any) are:
- Transport artifacts
- Client-facing contracts
- Application-specific
They are not a framework concern.
Plumego refuses to define a global numeric error space
because it would inevitably leak into business logic.
Framework-Level Errors
Plumego itself produces very few errors, and only at strict boundaries.
These errors are not exposed as structured error objects.
They are translated directly into HTTP responses.
Routing Errors
| Situation | HTTP Status |
|---|---|
| Route not found | 404 Not Found |
| Method not allowed | 405 Method Not Allowed |
These errors occur before handler execution.
No application code is involved.
Panic Recovery Errors (If Enabled)
If a panic recovery middleware is installed,
unexpected panics are typically translated to:
| Situation | HTTP Status |
|---|---|
| Unhandled panic | 500 Internal Server Error |
Plumego does not define the response body.
That is the responsibility of the recovery middleware.
What Plumego Does Not Provide
Plumego does not provide:
- A global error code registry
- Automatic error-to-response mapping
- Typed framework errors for business logic
- Error enums or constants
- Localization or message catalogs
If you are looking for plumego.ErrNotFound,
you are looking in the wrong place.
Application-Level Error Codes
If your system requires error codes,
they must be defined by the application, not the framework.
Common reasons include:
- Client-side branching logic
- Localization
- Analytics and monitoring
- Backward compatibility guarantees
Example:
{
"error": {
"code": "ORDER_NOT_CANCELLABLE",
"message": "order cannot be cancelled after shipment"
}
}
The structure, naming, and lifecycle of such codes
are application contracts.
Where Error Codes Should Live
A recommended layering:
| Layer | Responsibility |
|---|---|
| Domain | Semantic errors (no codes) |
| Usecase | Operational errors (no HTTP) |
| Handler | Error → HTTP mapping |
| API Contract | Error code definition |
Error codes belong at the API contract layer,
not in domain or usecase logic.
HTTP Status Codes vs Error Codes
HTTP status codes and error codes serve different purposes.
HTTP Status Codes
- Part of the HTTP protocol
- Coarse-grained
- Standardized
- Transport-level
Examples: 400, 401, 403, 404, 500
Application Error Codes
- Fine-grained
- Business- or domain-specific
- Defined by the API contract
- Optional
Do not try to encode all semantics into HTTP status codes.
Error Translation Is Explicit
In Plumego:
Errors are translated to responses explicitly at boundaries.
Typical pattern in a handler:
err := usecase.Execute(input)
if err != nil {
switch {
case errors.Is(err, domain.ErrForbidden):
ctx.JSON(403, errorResponse("FORBIDDEN", err))
case errors.Is(err, domain.ErrNotFound):
ctx.JSON(404, errorResponse("NOT_FOUND", err))
default:
ctx.JSON(500, errorResponse("INTERNAL_ERROR", nil))
}
return
}
Plumego does not perform this mapping for you.
This explicitness is a core guarantee.
Error Codes and Versioning
If you introduce error codes:
- They become part of the API contract
- Changing or removing them is a breaking change
- They must be versioned deliberately
Error codes are not implementation details.
Error Codes and Localization
Localization should be handled:
- On the client, using error codes
- Or at a dedicated presentation layer
Do not embed localized messages in domain errors.
Error codes are stable; messages are not.
Common Anti-Patterns
Framework-Level Error Codes
Trying to standardize error codes across all Plumego apps
defeats the framework’s neutrality.
Domain Errors with HTTP Semantics
return ErrBadRequest
Domain logic must not know about HTTP.
String-Based Error Matching
if err.Error() == "not found" { ... }
This is brittle and unsafe.
Silent Error Normalization
Automatically rewriting errors to “safe” responses
without explicit logic hides failures.
Testing Error Semantics
Error handling should be tested at the correct boundary:
- Domain tests assert semantic errors
- Usecase tests assert operational failures
- Handler tests assert HTTP + error code mapping
Do not test error codes in domain tests.
Summary
In Plumego:
- The framework defines almost no error codes
- HTTP status codes are transport-level only
- Application error codes are explicit contracts
- Error translation happens at boundaries
- Nothing is automatic or implicit
If an error code exists, it is there because you defined it —
and that is exactly how it should be.
Related Reference Pages
- Error Model (Concepts) — how errors propagate
- Handlers — where error translation happens
- Response — writing error responses explicitly
This page defines the absence of framework error codes —
and why that absence is a feature, not a gap.