{"record":{"id":"2f32b8e4c9775d2e","repo":"apache/pulsar","slug":"timeout-during-open-cursor-operation","errorCode":null,"errorMessage":"Timeout during open-cursor operation","messagePattern":"Timeout during open-cursor operation","errorType":"exception","errorClass":"ManagedLedgerException","httpStatus":null,"severity":"error","filePath":"managed-ledger/src/main/java/org/apache/bookkeeper/mledger/impl/ManagedLedgerImpl.java","lineNumber":999,"sourceCode":"        final Result result = new Result();\n\n        asyncOpenCursor(cursorName, initialPosition, properties, cursorProperties, new OpenCursorCallback() {\n            @Override\n            public void openCursorComplete(ManagedCursor cursor, Object ctx) {\n                result.cursor = cursor;\n                counter.countDown();\n            }\n\n            @Override\n            public void openCursorFailed(ManagedLedgerException exception, Object ctx) {\n                result.exception = exception;\n                counter.countDown();\n            }\n\n        }, null);\n\n        if (!counter.await(AsyncOperationTimeoutSeconds, TimeUnit.SECONDS)) {\n            throw new ManagedLedgerException(\"Timeout during open-cursor operation\");\n        }\n\n        if (result.exception != null) {\n            log.error().exception(result.exception).log(\"Error adding entry\");\n            throw result.exception;\n        }\n\n        return result.cursor;\n    }\n\n    @Override\n    public void asyncOpenCursor(final String cursorName, final OpenCursorCallback callback, Object ctx) {\n        this.asyncOpenCursor(cursorName, InitialPosition.Latest, callback, ctx);\n    }\n\n    @Override\n    public void asyncOpenCursor(final String cursorName, final InitialPosition initialPosition,\n            final OpenCursorCallback callback, final Object ctx) {","sourceCodeStart":981,"sourceCodeEnd":1017,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/managed-ledger/src/main/java/org/apache/bookkeeper/mledger/impl/ManagedLedgerImpl.java#L981-L1017","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Set managedLedgerOffloadBucket=<bucket-name> in broker.conf and restart the broker.","Verify the bucket exists in the target provider with the exact name (no typos, right cloud account/region).","Check that no later config source overrides the bucket with an empty value (env var PULSAR_PREFIX_ handling, topic policies)."],"exampleFix":"// before: broker.conf\nmanagedLedgerOffloadDriver=aws-s3\n\n// after:\nmanagedLedgerOffloadDriver=aws-s3\nmanagedLedgerOffloadBucket=my-pulsar-offload-bucket","handlingStrategy":"validation","validationCode":"if (config.getBucket() == null || config.getBucket().isEmpty()) {\n    throw new IllegalStateException(\"managedLedgerOffloadBucket must be set for driver \" + config.getDriver());\n}","typeGuard":null,"tryCatchPattern":"try {\n    provider.validate(tieringConfig);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"Bucket cannot be empty\")) {\n        log.error(\"Set managedLedgerOffloadBucket=<bucket> in broker.conf for driver {}\", tieringConfig.getDriver());\n    }\n    throw e;\n}","preventionTips":["Pair every managedLedgerOffloadDriver change with its required bucket property.","Verify the bucket exists in the target cloud account before enabling offload.","Watch for empty-string overrides from env/config precedence chains.","Run an offload smoke test on a test topic after every tiering config change."],"tags":["configuration","validation","offload","bucket"],"backgroundTag":"missing-config-property","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}