apache/pulsar · error · RuntimeException

Failed to delete the state value for key '%s'

Error message

Failed to delete the state value for key '%s'

What it means

BKStateStoreImpl.delete blocks on deleteAsync and rethrows failures as a RuntimeException with this message (cause not attached). It means deleting the key's value from the BookKeeper-backed state table failed asynchronously.

Source

Thrown at pulsar-functions/instance/src/main/java/org/apache/pulsar/functions/instance/state/BKStateStoreImpl.java:156

        } catch (Exception e) {
            throw new RuntimeException("Failed to update the state value for key '" + key + "'");
        }
    }

    @Override
    public CompletableFuture<Void> deleteAsync(String key) {
        return table.delete(
                Unpooled.wrappedBuffer(key.getBytes(UTF_8)),
                Options.delete()
        ).thenApply(ignored -> null);
    }

    @Override
    public void delete(String key) {
        try {
            result(deleteAsync(key));
        } catch (Exception e) {
            throw new RuntimeException("Failed to delete the state value for key '" + key + "'");
        }
    }

    @Override
    public CompletableFuture<ByteBuffer> getAsync(String key) {
        return table.get(Unpooled.wrappedBuffer(key.getBytes(UTF_8))).thenApply(
                data -> {
                    try {
                        if (data != null) {
                            ByteBuffer result = ByteBuffer.allocate(data.readableBytes());
                            data.readBytes(result);
                            // Set position to off the buffer to the beginning, since the position after the
                            // read is going to be end of the buffer
                            // If we do not rewind to the beginning here, users will have to explicitly do
                            // this in their function code
                            // in order to use any of the ByteBuffer operations
                            result.position(0);
                            return result;

View on GitHub (pinned to 820761864e)

Solutions

  1. Use deleteAsync to capture the real underlying exception.
  2. Check BookKeeper/table service health and retry the delete (deletes are idempotent).
  3. Confirm the state table for the function is open and healthy.
  4. Check for table-service errors around the time of failure in broker/storage logs.

Example fix

// before
store.delete("stale-key");
// after
store.deleteAsync("stale-key")
    .exceptionally(ex -> {
        log.warn("delete failed, key may already be gone", ex);
        return null;
    }).join();
Defensive patterns

Strategy: retry

Validate before calling

// deletes are idempotent; verify storage reachable first
store.getAsync(key).get(5, TimeUnit.SECONDS); // cheap pre-flight

Try / catch

try {
    store.delete(key);
} catch (RuntimeException e) {
    backoffRetry(() -> store.delete(key), 3); // idempotent, safe to retry
}

Prevention

When it happens

Trigger: Calling delete(key) when the table delete call fails: storage service unreachable, timeout, or table-service internal error while routing the delete to the owning bookie.

Common situations: Table service range/routing errors during re-balancing; bookie failures; deleting keys concurrently with table restore/compaction; network partition.

Related errors


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