apache/beam · error

Failed to extend visibility timeout for

Error message

Failed to extend visibility timeout for {} messages with expired receipt handles.

What it means

WARN logged by the SQS unbounded reader when a ChangeMessageVisibilityBatch response contains failures whose receipt handles have expired: those messages can no longer have their visibility timeout extended and will be redelivered by SQS. The reader partitions failures by handle validity and drops the expired ones from its pending-extend tracking (numExtendedDeadlines only counts real successes), relying on SQS at-least-once redelivery instead.

Solutions

  1. No code change needed for expired handles: SQS redelivers those messages and the reader reprocesses them
  2. If expiry is premature, extend visibility timeout earlier (smaller extension intervals) or increase the initial visibility timeout on the queue
  3. Make the downstream pipeline idempotent since redelivery means possible duplicates
Defensive patterns

Strategy: fallback

When it happens

Trigger: Thrown at sdks/java/io/amazon-web-services2/src/main/java/org/apache/beam/sdk/io/aws2/sqs/SqsUnboundedReader.java:861 when the library encounters an invalid state.

Common situations: See trigger scenarios.

Understand the failure class


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/6c09a28eb7413973. Report an issue: GitHub.

Appendix: source

Thrown at sdks/java/io/amazon-web-services2/src/main/java/org/apache/beam/sdk/io/aws2/sqs/SqsUnboundedReader.java:861

          response.failed().stream()
              .collect(partitioningBy(this::isHandleInvalid, mapping(e -> e.id(), toSet())));

      // Keep failed IDs only, but discard invalid (expired) receipt handles
      pendingExtends.keySet().retainAll(failures.getOrDefault(FALSE, ImmutableSet.of()));

      // Skip stats update and inFlight management if explicitly expiring messages for immediate
      // redelivery
      if (extensionSec > 0) {
        numExtendedDeadlines.add(nowMsSinceEpoch, response.successful().size());

        Set<String> invalidMsgIds = failures.getOrDefault(TRUE, ImmutableSet.of());
        if (invalidMsgIds.size() > 0) {
          // consider invalid (expired) messages no longer in flight
          numLateDeadlines.add(nowMsSinceEpoch, invalidMsgIds.size());
          for (String msgId : invalidMsgIds) {
            inFlight.remove(msgId);
          }
          LOG.warn(
              "Failed to extend visibility timeout for {} messages with expired receipt handles.",
              invalidMsgIds.size());
        }
      }

      retries += 1;
    }
  }

  @VisibleForTesting
  long getVisibilityTimeoutMs() {
    return visibilityTimeoutMs;
  }

  /** Log stats if time to do so. */
  private void stats() {
    long nowMsSinceEpoch = now();
    if (lastLogTimestampMsSinceEpoch < 0) {

View on GitHub (pinned to 12126d8942)