← All posts
Infra

SQS "ReceiptHandleIsInvalid" or Kafka "CommitFailedException"? Message-queue failures that cause silent duplicates

For developers and autonomous AI agents · ~5 min read

Message queues fail in a way that's especially nasty for agents: not with a loud error, but with a silent duplicate. The delete fails, the message comes back, and something processes it twice. Two errors — SQS ReceiptHandleIsInvalid and Kafka CommitFailedException — are the usual culprits, and both are about timing.

SQS: ReceiptHandleIsInvalid

You pulled a message, processed it, went to DeleteMessage — and got ReceiptHandleIsInvalid (or MessageNotInflight). The visibility timeout expired while you were still processing, so the message became visible again and your handle is stale. The real problem isn't the failed delete; it's that another consumer may have already picked the message up.

  1. Set the visibility timeout to ≥ 6x your processing/function timeout so processing finishes well within the window.
  2. Make processing idempotent — if a duplicate does slip through, handling it twice is harmless.
  3. Set maxReceiveCount ≥ 5 with a dead-letter queue so a genuinely poison message is quarantined, not looped.

Kafka: CommitFailedException

Your consumer threw CommitFailedException. It means your poll loop took longer than max.poll.interval.ms (default 300000ms), so the broker decided the consumer was dead and rebalanced the partition to another consumer. You no longer own it.

Do NOT retry the commit. You've been rebalanced — committing now is meaningless, and the messages you were processing are already being handled by whoever got the partition (a silent duplicate). Reduce max.poll.records so each batch finishes within the interval, or raise max.poll.interval.ms — and make processing idempotent for the in-flight duplicate.

For agents consuming queues

An agent that retries the failed delete/commit makes the duplicate problem worse. diagnose_infra_error returns the message-queue family with the correct fix — adjust the timeout/poll settings, don't retry the commit, and lean on idempotency:

diagnose_infra_error({error: "kafka CommitFailedException poll interval"})
// → { family: "message-queue",
//      fix: "you were rebalanced — don't retry the commit; reduce max.poll.records; make processing idempotent" }
For AI agents

Machine-readable guide: https://snapback.sh/llms.txt · Tool discovery: https://snapback.sh/.well-known/mcp.json · MCP endpoint: https://api.snapback.sh/mcp. Free tools need no token; pay-per-call diagnosis via x402 on Solana or EVM (~$0.0032 USDC).

Try Snapback freeRead the docs