apache/pulsar · error · RuntimeException

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

Error message

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

What it means

BKStateStoreImpl.put blocks on putAsync and wraps failures in a RuntimeException with this message (cause again omitted from the message chain). It means a synchronous state-value write into the BookKeeper-backed state table failed after the future completed exceptionally.

Source

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

            // to create a ByteBuffer to store to the state store
            // the position of the buffer will be at the end and nothing will be written to table service
            value.position(0);
            return table.put(
                    Unpooled.wrappedBuffer(key.getBytes(UTF_8)),
                    Unpooled.wrappedBuffer(value));
        } else {
            return table.put(
                    Unpooled.wrappedBuffer(key.getBytes(UTF_8)),
                    null);
        }
    }

    @Override
    public void put(String key, ByteBuffer value) {
        try {
            result(putAsync(key, value));
        } 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 + "'");
        }

View on GitHub (pinned to 820761864e)

Solutions

  1. Inspect logs/table-layer errors for the underlying cause (timeout, storage failure).
  2. Use putAsync to obtain the actual exception from the failed future.
  3. Check value size against the state server limits and shrink or compress the value.
  4. Verify BookKeeper storage health (disk space, bookie availability).

Example fix

// before
store.put("key", value); // throws without cause detail
// after
store.putAsync("key", value)
    .exceptionally(ex -> {
        log.error("put failed for key", ex);
        return null;
    }).join();
Defensive patterns

Strategy: validation

Validate before calling

// before putting state
if (key == null || key.isEmpty()) throw new IllegalArgumentException("state key required");
int maxStateValueBytes = 1_000_000; // align with server limits
if (value != null && value.remaining() > maxStateValueBytes) {
    throw new IllegalArgumentException("state value too large: " + value.remaining());
}

Try / catch

try {
    store.put(key, value);
} catch (RuntimeException e) {
    if (isTransient(e)) backoffRetry(() -> store.put(key, value), 3);
    else throw e;
}

Prevention

When it happens

Trigger: Calling put(key, value) when the table put fails: storage service down, request timeout, table in bad state, or a null value path behaving differently than expected (null values are not written via the table here).

Common situations: Oversized state values exceeding server limits; BookKeeper write failures (disk full, quorum loss); function state table corruption; network issues between instance and storage proxy.

Related errors


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