apache/pulsar · error · ManagedLedgerException
Timeout during delete operation
Error message
Timeout during delete operation
What it means
The TRANSIENT (local filesystem) jcloud provider's validate() checks that a bucket is configured and throws IllegalArgumentException when config.getBucket() is null or empty. For the 'transient' (Local) offload driver the bucket maps to the local directory used to store offloaded data, so it is mandatory.
Source
Thrown at managed-ledger/src/main/java/org/apache/bookkeeper/mledger/impl/ManagedCursorImpl.java:2566
public void deleteFailed(ManagedLedgerException exception, Object ctx) {
result.exception = exception;
if (timeout.get()) {
log.warn()
.attr("positions", positions)
.log("Delete operation timeout, callback deleteFailed");
}
counter.countDown();
}
}, null);
if (!counter.await(ManagedLedgerImpl.AsyncOperationTimeoutSeconds, TimeUnit.SECONDS)) {
timeout.set(true);
log.warn()
.attr("positions", positions)
.log("Delete operation timeout, no callback triggered");
throw new ManagedLedgerException("Timeout during delete operation");
}
if (result.exception != null) {
throw result.exception;
}
}
@Override
public void asyncDelete(Iterable<Position> positions, AsyncCallbacks.DeleteCallback callback, Object ctx) {
if (isClosed()) {
callback.deleteFailed(new ManagedLedgerException
.CursorAlreadyClosedException("Cursor was already closed"), ctx);
return;
}
Position newMarkDeletePosition = null;
View on GitHub (pinned to 820761864e)
Solutions
- Set managedLedgerOffloadBucket=<local-directory-name> in broker.conf (or the topic-level offload properties).
- Confirm the driver you intend is actually selected — if you meant cloud offload, set managedLedgerOffloadDriver correctly (e.g. s3) and supply its config.
- Ensure the property is in the right config file that the broker/offloader loads and was not overridden by an empty value in a higher-priority source.
Example fix
// before: broker.conf managedLedgerOffloadDriver=transient # no bucket configured // after: managedLedgerOffloadDriver=transient managedLedgerOffloadBucket=pulsar-offload-local
Defensive patterns
Strategy: validation
Validate before calling
// before enabling transient offload, check the effective config
if (config.getBucket() == null || config.getBucket().isEmpty()) {
throw new IllegalStateException("managedLedgerOffloadBucket must be set for transient/local offload");
} Try / catch
try {
provider.validate(tieringConfig);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("Bucket cannot be empty")) {
log.error("Add managedLedgerOffloadBucket to broker.conf for the configured driver");
}
throw e;
} Prevention
- Add managedLedgerOffloadBucket whenever you set a managedLedgerOffloadDriver.
- Smoke-test offload configuration with a test topic after broker config changes.
- Grep your broker.conf for empty managedLedgerOffload* overrides.
- Document required per-driver properties in your deployment templates.
When it happens
Trigger: Running offload with driver configured to the transient/local provider while managedLedgerOffloadBucket (TieredStorageConfiguration.getBucket()) is not set in broker.conf or the offload request properties.
Common situations: Testing local offload without setting managedLedgerOffloadBucket, copying config from a cloud provider example that omits the bucket, or bucket set under the wrong namespace/property name so the offloader sees empty.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Timeout during open-cursor operation
- Timeout during close operation
- Timeout during delete-cursors operation
- Timeout during managed ledger terminate
- The '${offloaderName}' offloader does not provide an offload
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/8d2406731882eb81.
Report an issue: GitHub.