gobridge

Troubleshooting by shared.ErrorCode

Every error returned across a GoBridge port carries a *shared.BridgeError with a stable ErrorCode (defined in domain/shared/errors.go) and an ErrorClass (transient / permanent / expired / rejected) that drives runtime routing decisions (retry, DLQ, drop). This page is the operator-facing index: when a code shows up in logs, metrics, or DLQ entries, find the section here for what it means and how to recover.

For the architectural model, see ARCHITECTURE.md §15 — Error Classification. For the canonical names, see the shared kernel rows in UBIQUITOUS.md.

Recovery actions below are operator-side. The runtime already retries transient codes per the route’s BackoffPolicy, sends permanent codes to the DLQ (when configured), routes expired codes through the route’s ExpiredAction, and drops rejected codes silently. Manual recovery only applies after the automated path is exhausted or when the underlying cause must be fixed at the source.

How to use this page

  1. Find the code field in your structured log line or DLQ entry (DLQEntry.ErrorCode). Error codes are not exposed as a metric tag; the runtime emits a single route-scoped counter, RouteErrors (tagged route_id), for the aggregate error rate per route.
  2. Jump to the matching section below.
  3. Apply the recovery action; if a metric is listed under “Related metrics”, verify the fix by watching it return to baseline.

Transient codes (auto-retried)

These represent recoverable conditions. The runtime retries with backoff; they only need operator attention when the rate stays elevated or the route hits its MaxRetries and the envelope lands in the DLQ.

TIMEOUT

CONNECTION_LOST

UNAVAILABLE

THROTTLED

BROKER_BUSY

TEMPORARY_AUTH_FAILURE

NO_ROUTE_OWNER

FORWARD_FAILED

PROCESSOR_TIMEOUT

Permanent codes (DLQ-bound)

Retry will not help. The runtime sends these to the DLQ (when configured) or drops per the route’s FailureAction. Operator action is required at the source of the failure.

NOT_AUTHORIZED

FORBIDDEN

NOT_FOUND

INVALID_CONFIG

INVALID_PAYLOAD

Special case — MQTT plaintext-credential startup failure. A likely first-run failure: the build (or a credential rotation) fails closed with

mqtt: username/password are sent in the MQTT CONNECT packet in cleartext but
not all broker_urls use a TLS scheme; use ssl:// (or mqtts://, tls://,
mqtt+ssl://, tcps://, wss://), or set allow_plaintext_credentials=true to
send credentials in cleartext anyway

MQTT sends CONNECT credentials in cleartext, and autopaho selects TLS purely from the URL schemetls.enable on a tcp:// URL is a silent no-op. Recovery: change every broker_urls entry to a TLS scheme (usually just tcp://ssl:// plus the broker’s TLS port), or — only on a trusted transport such as a private mesh or localhost test broker — set options.session.allow_plaintext_credentials: true. The same gate re-runs on credential rotation, so a rotation that first introduces credentials can trip it at runtime too.

PAYLOAD_TOO_LARGE

INVALID_TOPIC

PROTOCOL_ERROR

SCHEMA_VIOLATION

QOS_NOT_SUPPORTED

NOT_SUPPORTED

VERSION_MISMATCH

ALREADY_EXISTS

STALE_FENCING_TOKEN

DUPLICATE_RECORD

MESSAGE_EXPIRED

PROCESSOR_PANIC

INTERNAL

INVALID_OUTBOX_RECORD

OUTBOX_NOT_CLAIMABLE

OUTBOX_NOT_IN_CLAIMED_STATE

OUTBOX_ALREADY_TERMINAL

Rejected codes (silent drop)

The runtime drops these envelopes without sending them to the DLQ (the envelope is being deliberately filtered or rejected as malformed input the bridge cannot meaningfully retain).

MESSAGE_FILTERED

Runtime-only codes

NO_BINDING_MATCH

POISON_MESSAGE

The adapter and runtime diagnostic counters — what each one means when it climbs — are on their own page: Adapter and runtime diagnostic metrics.

Quick reference

Code Class DLQ?
TIMEOUT, CONNECTION_LOST, UNAVAILABLE, THROTTLED, BROKER_BUSY, TEMPORARY_AUTH_FAILURE, NO_ROUTE_OWNER, FORWARD_FAILED, PROCESSOR_TIMEOUT transient Only after retries exhausted
NOT_AUTHORIZED, FORBIDDEN, NOT_FOUND, INVALID_CONFIG, PROTOCOL_ERROR, QOS_NOT_SUPPORTED, NOT_SUPPORTED, VERSION_MISMATCH, ALREADY_EXISTS, STALE_FENCING_TOKEN, DUPLICATE_RECORD, PROCESSOR_PANIC, INTERNAL, INVALID_OUTBOX_RECORD, OUTBOX_NOT_CLAIMABLE, OUTBOX_NOT_IN_CLAIMED_STATE, OUTBOX_ALREADY_TERMINAL, NO_BINDING_MATCH, POISON_MESSAGE permanent Yes (per route FailureAction)
INVALID_PAYLOAD, PAYLOAD_TOO_LARGE, INVALID_TOPIC, SCHEMA_VIOLATION, MESSAGE_FILTERED rejected No (silent drop)
MESSAGE_EXPIRED expired Per route ExpiredAction

The authoritative source is domain/shared/errors.go; this page must stay in lockstep with that file.