Docs Error Codes and Error Semantics

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.


  • 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.