wireerror

package
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 29, 2026 License: Apache-2.0, MIT Imports: 6 Imported by: 0

Documentation

Overview

Package wireerror is the error contract: the typed, wavefront-originated failures returned to a client as a proper HTTP status + standard headers + the `X-Wavefront-Error` code + a fixed `wavefront.v0.Error` protobuf body. Established in v0.1 and stable through v1.0 (iterated additively). The code/ status/header table here is authoritative against docs/protocol.md.

Index

Constants

View Source
const (
	HeaderContentType     = "Content-Type"
	HeaderContractVersion = "X-Wavefront-Contract-Version"
	HeaderWavefrontError  = "X-Wavefront-Error"
)

Wavefront response header names that the wire-error envelope owns — kept here, alongside the codes, so the server and any other emitter cannot drift from the protocol definition.

View Source
const MediaTypeProtobuf = "application/protobuf"

MediaTypeProtobuf is the single request and response media type the v0.1 codec contract names. Every wire-error envelope has Content-Type set to this value; an inbound request that carries a body must declare it. A future multi-codec selector (issue #44) would replace direct comparison against this constant with a per-codec table.

View Source
const VersionUnknown = "unknown"

VersionUnknown is the X-Wavefront-Contract-Version value to send when negotiation has not resolved a real version yet — a pre-negotiate error, a panic before the bundle is consulted, or any other path that lacks request context. It keeps the header well-defined on every response, success or error, as docs/protocol.md requires.

Variables

This section is empty.

Functions

func Write added in v0.5.0

func Write(w http.ResponseWriter, werr *Error, contractVersion string)

Write emits a wavefront-originated failure as a fully-formed wire-error envelope: status, standard + extension headers, and the protobuf body. It is the single path every emitter calls — direct callers in handlers, the panic-recovery middleware, and any future emitter must go through this function so the on-wire shape cannot drift.

contractVersion is the value sent in X-Wavefront-Contract-Version; pass VersionUnknown when no negotiation has resolved a real version yet.

Types

type Error

type Error struct {
	// contains filtered or unexported fields
}

Error is a typed, wavefront-originated failure. It satisfies the error interface so it can flow through normal Go error handling.

`status` is per-instance rather than per-code because `upstream_status` parameterizes the HTTP status across the bounded passthrough set {401,403,404,405,409,410,422,429,451}. Every other code in the table has a fixed status — passed at construction and never varied.

`retryAfter` is the verbatim header value to emit. It is empty for every code except `upstream_timeout` (which fixes it to "0"), `upstream_status` on a 429 whose upstream supplied a Retry-After header, and `unavailable` emitted by the proxy bundle-gate (which attaches a short fixed hint so clients back off briefly during boot).

func DecodeFailed

func DecodeFailed(msg string) *Error

DecodeFailed — the client body did not decode into the contract's request_message. 400.

func InternalError added in v0.5.0

func InternalError(msg string) *Error

InternalError — an unrecoverable fault inside wavefront itself: a panic in the request path, a programmer error caught at runtime, anything that is not a client / upstream condition. 500. The detail message should not leak internals to clients; callers pass a short, fixed string and rely on logs for the panic value and stack trace.

func RequestBodyTooLarge

func RequestBodyTooLarge(msg string) *Error

RequestBodyTooLarge — the inbound body exceeded WAVEFRONT_MAX_BODY_BYTES. 413.

func TransformFailedRequest added in v0.2.0

func TransformFailedRequest(msg string) *Error

TransformFailedRequest — a request transform verb could not apply: the decoded request is well-formed but unprocessable under this contract's mapping. 422 (RFC 9110 §15.5.21).

func TransformFailedResponse added in v0.2.0

func TransformFailedResponse(msg string) *Error

TransformFailedResponse — a response transform verb could not apply: the live internal shape drifted from the bundle's response stanzas. Same fault class as upstream_error. 502.

func Unavailable added in v0.5.0

func Unavailable(msg string) *Error

Unavailable — the proxy cannot serve right now because the bundle is not loaded yet. 503. Issue #39's matrix extends this code — used on the /ready ops endpoint since v0.1 — to the proxy data path: a request that races bundle-load at boot returns this envelope rather than the misleading `upstream_error` 502 it used to (there is no upstream involved). The caller is expected to attach a short Retry-After hint with `.WithRetryAfter(...)` so well-behaved clients back off briefly and retry. Graceful drain is handled implicitly by http.Server.Shutdown (the bundle pointer is never cleared at shutdown), so accepted requests in the drain window still find a live bundle and finish normally.

func UnknownRoute added in v0.5.0

func UnknownRoute(msg string) *Error

UnknownRoute — no contract in the bundle binds the inbound request's (path, method). Wrong-method folds into this code: a request whose path matches a registered route but whose method differs returns the same envelope (no 405, no `Allow` header), because each contract names exactly one method and the bundle is the only routing source of truth. 404.

func UnsupportedContractVersion

func UnsupportedContractVersion(msg string) *Error

UnsupportedContractVersion — the contract-version header is missing, unknown, or unsupported. 400.

func UnsupportedMediaType added in v0.5.0

func UnsupportedMediaType(msg string) *Error

UnsupportedMediaType — the inbound request declared a Content-Type that is not the contract's protobuf media type. Distinct from `decode_failed`: a wrong envelope is rejected before the body is read, so this code is reserved for the envelope mismatch and `decode_failed` is reserved for a valid envelope whose bytes don't parse. 415 (RFC 9110 §15.5.16).

func UpstreamError

func UpstreamError(msg string) *Error

UpstreamError — the upstream returned a non-2xx, was unreachable, or its reply could not be encoded. 502.

func UpstreamStatus added in v0.5.0

func UpstreamStatus(httpStatus int, msg string) *Error

UpstreamStatus — the upstream returned a status in the bounded passthrough set {401, 403, 404, 405, 409, 410, 422, 429, 451}. The upstream's status is preserved on the response (so a 401 stays a 401); the body is the standard wavefront.v0.Error envelope so the body type invariant holds. This is the first wire-error code whose HTTP status is parameterized — every other constructor pins a fixed status.

For an upstream 429, the caller can attach the upstream's Retry-After value with `.WithRetryAfter(...)`; the header is relayed verbatim. For any other passthrough code, Retry-After is not emitted.

func UpstreamTimeout

func UpstreamTimeout(msg string) *Error

UpstreamTimeout — the upstream exceeded WAVEFRONT_REQUEST_TIMEOUT_MS. 504.

func (*Error) Code

func (e *Error) Code() string

func (*Error) Error

func (e *Error) Error() string

func (*Error) HTTPStatus

func (e *Error) HTTPStatus() int

func (*Error) Headers

func (e *Error) Headers() http.Header

Headers is the standard + extension header set for this failure. Content-Type is always the protobuf media type; Retry-After is set only where retrying is semantically meaningful. The X-Wavefront-Error / X-Wavefront-Contract-Version headers are written by the server (the latter needs request context the error itself does not carry).

func (*Error) Message

func (e *Error) Message() string

func (*Error) ProtoBody

func (e *Error) ProtoBody() []byte

ProtoBody is the marshaled wavefront.v0.Error response body.

func (*Error) WithRetryAfter added in v0.5.0

func (e *Error) WithRetryAfter(v string) *Error

WithRetryAfter returns a shallow copy of e with the given Retry-After header value attached. An empty string is a no-op so callers can pass `uresp.Header.Get("Retry-After")` directly without branching on presence. Used by the upstream 429 passthrough and by the proxy bundle-gate's `unavailable` emission; other codes either set Retry-After at construction (upstream_timeout's fixed "0") or never emit it.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL