KubeMQ
ConnectorsGoogle Cloud Pub/SubReference

Error Codes

The gRPC status codes the KubeMQ Pub/Sub connector returns — the exactly-once invalid-ack FAILED_PRECONDITION deviation and common INVALID_ARGUMENT triggers.

The connector speaks the real Pub/Sub v1 gRPC services, so it returns genuine gRPC status codes (google.rpc.Code) — standard Google client libraries surface them as the normal typed exceptions (InvalidArgument, FailedPrecondition, NotFound, …). There is no REST/JSON v1 (gRPC only), so there are no XML error envelopes.

The one contract that differs from a naive implementation: the exactly-once unary invalid-ack path returns FAILED_PRECONDITION + an ErrorInfo, not INVALID_ARGUMENT — matching the real Google SDK contract (the SDK resolves the ack result from the ErrorInfo.reason).

gRPC status code table

gRPC statusTriggerResolution / recovery
INVALID_ARGUMENTA validation failure: bad resource id (not 3..255, not letter-led, bad charset, goog prefix, topic id starting sub.); batch > 1000; message > 10 MiB; > 100 attributes; attr key > 256 B / value > 1024 B / ordering key > 1024 B; empty data and attributes; malformed CEL filter (> 256 chars or syntax error); max_delivery_attempts outside 5..100; a schema definition that fails to parse or exceeds 300 KB; a message that fails schema enforce-on-publish; a rejected ingestion or export (BigQuery / Cloud Storage / Bigtable) subscriptionFix the value, then retry. Bring the resource id, batch size, message size, or attribute count inside the limits in Limits & Rules; set max_delivery_attempts to 5..100; correct the filter syntax / length; make the payload conform to the schema; supply non-empty data or attributes. Do not blind-retry — the input is rejected deterministically. Ingestion / export subscriptions are unsupported
FAILED_PRECONDITIONPull on a detached subscription; CreateSnapshot of a detached subscription; and — on an exactly-once subscription — a unary Acknowledge / ModifyAckDeadline with an unparseable / expired / unknown ack_id (carries the ErrorInfo below)Detached: re-attach the subscription (or target an attached one) before pulling / snapshotting. Stale exactly-once ack_id: do not re-ack a message you already settled — the id is spent; just re-pull for a fresh lease and ack_id. If it recurs across nodes, enable sticky load balancing (below)
NOT_FOUNDOperating on a topic / subscription / snapshot / schema that is not in the registryCreate the resource first (CreateTopic / CreateSubscription / CreateSnapshot / CreateSchema), then retry; or correct the id. On a cluster, a NOT_FOUND for a record that does exist usually means you hit a different node — enable sticky load balancing
ALREADY_EXISTSCreating a resource id that already existsTreat as idempotent success — the resource is already there. Get it instead of creating it, or pick a different id
UNAVAILABLEA StreamingPull stream the server periodically closes after StreamCloseSeconds (default 1800 s / 30 min) — SDKs transparently reconnect. Also the traffic-gate response when the broker is not readyLet the SDK auto-reconnect — periodic stream close is normal and your Subscribe callback keeps running across it; no action needed. For the traffic gate, retry with backoff until the broker is ready, and confirm the connector is up on :8085 (PUBSUB_EMULATOR_HOST correct)

Batch atomicity. A Publish validates the entire batch before enqueuing anything; the first offending message rejects the whole batch with INVALID_ARGUMENT and nothing is published. See Publishing.

Exactly-once ack results

On a subscription with enable_exactly_once_delivery, ack failures are reported differently per path.

StreamingPull — confirmation messages

The server returns an AcknowledgeConfirmation / ModifyAckDeadlineConfirmation carrying two id lists; the SDK retries accordingly:

ListMeaningClient action
invalid_ack_idsexpired / unknown / wrong-node ids — permanently unackablegive up on those ids
temporary_failed_ack_idsa transient broker failureretry those ids

Unary Acknowledge / ModifyAckDeadline — status + ErrorInfo

status:  FAILED_PRECONDITION
details: ErrorInfo{ reason: "PERMANENT_FAILURE_INVALID_ACK_ID" }

This is the real Google SDK contract — the SDK reads the ack result from the ErrorInfo.reason, not from a literal INVALID_ARGUMENT. A connector that returned INVALID_ARGUMENT here would break the SDK's exactly-once bookkeeping.

Node-local boundary (gotcha #1). An ack_id is minted with the node id baked in; presenting it to a different node (after a failover or a non-sticky load balancer) makes it appear as an invalid id — invalid_ack_ids on StreamingPull, FAILED_PRECONDITION + ErrorInfo on unary. Pin a subscription's StreamingPull to one node, or accept at-least-once across nodes.

Common triggers by scenario

ScenarioResultResolution / recovery
Pull on an empty subscriptionnone — returns with no messagesNone — expected; keep polling
ModifyAckDeadline(0)none — immediate nack/redeliverNone — this is the nack; the message redelivers
Ack deadline expires before acknone — 250 ms sweeper redelivers; receive count++Ack within the deadline, or extend it for slow handlers
Receive count exceeds max_delivery_attempts (DLQ set)none — republished to dead_letter_topic, original ackedSubscribe to the dead-letter topic to inspect / replay
Receive count exceeds max_delivery_attempts (no DLQ)none — dropped after exhaustionAttach a dead-letter topic if you cannot afford to drop poison messages
Seek to a timestamp before the retained windownone — clamps to the earliest retained message (gotcha #8)None — expected clamp; widen retention to replay further back
Seek that would replay more than MaxSeekReplaynone — stops at the cap, logs WARN (no silent loss)None — raise MaxSeekReplay (operator config) if a larger replay is required
Publish to a topic with zero subscriptionsnone — succeeds; written to the topic log, no fan-outNone — create a subscription before publishing if you need delivery
Filtered-out message during fan-outnone — never enqueued (≈ auto-acked)None — relax the subscription filter if the drop was unintended
kms_key_name on CreateTopicnone — accepted and ignoredNone — CMEK is a no-op on the emulator protocol
Bad resource id / oversize batch / oversize message / bad filter / schema mismatchINVALID_ARGUMENTFix the offending value against Limits & Rules and retry; do not blind-retry
Ingestion source / export subscriptionINVALID_ARGUMENTUnsupported — use a supported subscription type (pull / push)
Pull on a detached subscriptionFAILED_PRECONDITIONRe-attach the subscription (or pull from an attached one)
Snapshot of a detached subscriptionFAILED_PRECONDITIONRe-attach before CreateSnapshot
Exactly-once unary ack with invalid / expired / wrong-node idFAILED_PRECONDITION + ErrorInfo(PERMANENT_FAILURE_INVALID_ACK_ID)Do not re-ack a settled message — re-pull for a fresh ack_id; if cross-node, enable sticky load balancing
Operate on a non-existent topic / sub / snapshot / schemaNOT_FOUNDCreate the resource first (or fix the id); on a cluster, enable sticky load balancing
Create a resource id that already existsALREADY_EXISTSTreat as idempotent success; get the resource or choose a new id
StreamingPull periodic close (every StreamCloseSeconds)UNAVAILABLE (SDK reconnects)None — let the SDK auto-reconnect; the callback keeps running
Broker not ready (traffic gate)UNAVAILABLERetry with backoff until ready; confirm the connector is up on :8085
data and attributes both emptyINVALID_ARGUMENTSupply non-empty data or at least one attribute, then retry

Recovery cheat-sheet

The recovery columns above collapse to five rules:

  1. UNAVAILABLE → transient. Let the SDK auto-reconnect; for the traffic gate, retry with backoff and confirm the connector is up on :8085 (PUBSUB_EMULATOR_HOST correct).
  2. INVALID_ARGUMENTfix the input, then retry (never blind-retry). Most often: max_delivery_attempts back into 5..100, a malformed CEL filter, an oversize batch / message / attribute, a schema mismatch, or empty data + attributes.
  3. FAILED_PRECONDITION → for an exactly-once stale ack_id, do not re-ack the already-settled message — re-pull for a fresh lease; for a detached subscription, re-attach before Pull / CreateSnapshot.
  4. NOT_FOUNDcreate the topic / subscription / snapshot / schema first (or fix the id).
  5. Node-local ack errors on a cluster (invalid_ack_ids, or FAILED_PRECONDITION / NOT_FOUND for records that exist) → enable sticky load balancing (session affinity) so a subscription's StreamingPull stays pinned to one node, or accept at-least-once across nodes.

Was this page helpful?

On this page