apache/pulsar · error · ManagedLedgerException

ManagedLedgerException (wrapped from err in OffloadedLedgerM

Error message

ManagedLedgerException (wrapped from err in OffloadedLedgerMetadataConsumer)

What it means

During getOffloadPoliciesBacklog / metadata page scans, BlobStoreManagedLedgerOffloader iterates offloaded-ledger metadata pages with a consumer. If the consumer (OffloadedLedgerMetadataConsumer) throws for any reason, the exception is logged and re-wrapped via ManagedLedgerException.getManagedLedgerException(err) so it surfaces as a ManagedLedgerException to managed-ledger callers.

Source

Thrown at tiered-storage/jcloud/src/main/java/org/apache/bookkeeper/mledger/offload/jcloud/impl/BlobStoreManagedLedgerOffloader.java:773

                    .uuid(contextUuid)
                    .ledgerId(ledgerId != null ? ledgerId : -1)
                    .lastModified(lastModified != null ? lastModified.getTime() : 0)
                    .size(size != null ? size : -1)
                    .uri(uri != null ? uri.toString() : null)
                    .userMetadata(userMetadata != null ? userMetadata : Collections.emptyMap())
                    .build();
            try {
                boolean canContinue = consumer.accept(offloadedLedgerMetadata);
                if (!canContinue) {
                    log.info("Iteration stopped by the OffloadedLedgerMetadataConsumer");
                    return null;
                }
            } catch (Exception err) {
                log.error().exception(err).log("Error in OffloadedLedgerMetadataConsumer");
                if (err instanceof InterruptedException) {
                    Thread.currentThread().interrupt();
                }
                throw ManagedLedgerException.getManagedLedgerException(err);
            }
        }
        log.info().attr("nextMarker", pages.getNextMarker()).log("Page scan complete");
        return pages.getNextMarker();
    }

}

View on GitHub (pinned to 820761864e)

Solutions

  1. Read the wrapped cause (ManagedLedgerException#getCause) to find the real storage/processing failure and fix it
  2. Verify blob-store list permissions and connectivity for the offload bucket
  3. For InterruptedException, restore the interrupt and retry after the broker's shutdown completes
  4. Retry the scan/backlog operation once the storage backend is healthy

Example fix

// caller
try { offloader.scanOffloadedLedgers(marker, consumer); }
catch (ManagedLedgerException mle) {
  log.warn("scan failed: {}", mle.getCause()); // look here for root cause
}
Defensive patterns

Strategy: try-catch

Validate before calling

// preflight: confirm the offload bucket is listable
ListObjectsV2Request req = new ListObjectsV2Request()
    .withBucketName(offloadBucket).withMaxKeys(1);
s3Client.listObjectsV2(req); // fails fast on perms/creds/network

Try / catch

try {
  offloader.scanOffloadedLedgers(marker, consumer);
} catch (ManagedLedgerException e) {
  Throwable root = rootCause(e);
  if (root instanceof InterruptedException) {
    Thread.currentThread().interrupt(); // honor shutdown
  } else {
    log.error("offload metadata scan failed: {}", String.valueOf(root));
  }
}

Prevention

When it happens

Trigger: A page-scan consumer (listing offloaded ledger metadata in the blob store) throws — storage client errors, parse errors in the consumer's handling, or InterruptedException while waiting — and the loop catches Exception and converts it.

Common situations: Listing objects in an S3/GCS bucket fails (credentials, throttling, network); consumer logic bug while processing offload metadata; broker shutdown interrupting the scan.

Related errors


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/372c60c863d6c7c8. Report an issue: GitHub.