apache/pulsar · error · ManagedLedgerException

Timeout during open-cursor operation

Error message

Timeout during open-cursor operation

What it means

The shared VALIDATION lambda throws this IllegalArgumentException when TieredStorageConfiguration.getBucket() is null or empty. Every jcloud offload driver requires a bucket name (or container/local directory, depending on provider) where ledger data is stored.

Source

Thrown at managed-ledger/src/main/java/org/apache/bookkeeper/mledger/impl/ManagedLedgerImpl.java:999

        final Result result = new Result();

        asyncOpenCursor(cursorName, initialPosition, properties, cursorProperties, new OpenCursorCallback() {
            @Override
            public void openCursorComplete(ManagedCursor cursor, Object ctx) {
                result.cursor = cursor;
                counter.countDown();
            }

            @Override
            public void openCursorFailed(ManagedLedgerException exception, Object ctx) {
                result.exception = exception;
                counter.countDown();
            }

        }, null);

        if (!counter.await(AsyncOperationTimeoutSeconds, TimeUnit.SECONDS)) {
            throw new ManagedLedgerException("Timeout during open-cursor operation");
        }

        if (result.exception != null) {
            log.error().exception(result.exception).log("Error adding entry");
            throw result.exception;
        }

        return result.cursor;
    }

    @Override
    public void asyncOpenCursor(final String cursorName, final OpenCursorCallback callback, Object ctx) {
        this.asyncOpenCursor(cursorName, InitialPosition.Latest, callback, ctx);
    }

    @Override
    public void asyncOpenCursor(final String cursorName, final InitialPosition initialPosition,
            final OpenCursorCallback callback, final Object ctx) {

View on GitHub (pinned to 820761864e)

Solutions

  1. Set managedLedgerOffloadBucket=<bucket-name> in broker.conf and restart the broker.
  2. Verify the bucket exists in the target provider with the exact name (no typos, right cloud account/region).
  3. Check that no later config source overrides the bucket with an empty value (env var PULSAR_PREFIX_ handling, topic policies).

Example fix

// before: broker.conf
managedLedgerOffloadDriver=aws-s3

// after:
managedLedgerOffloadDriver=aws-s3
managedLedgerOffloadBucket=my-pulsar-offload-bucket
Defensive patterns

Strategy: validation

Validate before calling

if (config.getBucket() == null || config.getBucket().isEmpty()) {
    throw new IllegalStateException("managedLedgerOffloadBucket must be set for driver " + config.getDriver());
}

Try / catch

try {
    provider.validate(tieringConfig);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("Bucket cannot be empty")) {
        log.error("Set managedLedgerOffloadBucket=<bucket> in broker.conf for driver {}", tieringConfig.getDriver());
    }
    throw e;
}

Prevention

When it happens

Trigger: Initializing a blob store / starting offload with managedLedgerOffloadBucket unset or empty for any driver using VALIDATION (aws, gcs, azureblob, transient paths that fall through to it).

Common situations: New broker deployment missing managedLedgerOffloadBucket, property defined but empty string, bucket configured only in namespace policy but topic offload uses broker config, or renamed property after a Pulsar upgrade.

Understand the failure class

Related errors


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