apache/pulsar · warning · RestException

key '%s' doesn't exist.

Error message

key '%s' doesn't exist.

What it means

The state store returned no StateValue for the requested key, so the worker throws a 404 RestException "key '<key>' doesn't exist.". The function exists and the state store is reachable; only the key lookup came back empty.

Source

Thrown at pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/ComponentImpl.java:1276

            log.error().attr("tenant", tenant).attr("namespace", namespace).attr("componentName", functionName)

                    .attr("key", key).exception(e).log("Invalid getFunctionState request @ / / / /");
            throw new RestException(Status.BAD_REQUEST, e.getMessage());
        }

        FunctionMetaDataManager functionMetaDataManager = worker().getFunctionMetaDataManager();
        if (!functionMetaDataManager.containsFunction(tenant, namespace, functionName)) {
            log.warn().attr("tenant", tenant).attr("namespace", namespace).attr("componentName", functionName)

                    .log("getFunctionState does not exist @ / / /");
            throw new RestException(Status.NOT_FOUND, String.format("'%s' is not found", functionName));
        }

        try {
            DefaultStateStore store = worker().getStateStoreProvider().getStateStore(tenant, namespace, functionName);
            StateValue value = store.getStateValue(key);
            if (value == null) {
                throw new RestException(Status.NOT_FOUND, "key '" + key + "' doesn't exist.");
            }
            byte[] data = value.getValue();
            if (data == null) {
                throw new RestException(Status.NOT_FOUND, "key '" + key + "' doesn't exist.");
            }

            ByteBuffer buf = ByteBuffer.wrap(data);

            Long number = null;
            if (buf.remaining() == Long.BYTES) {
                number = buf.getLong();
            }
            if (Boolean.TRUE.equals(value.getIsNumber())) {
                return new FunctionState(key, null, null, number, value.getVersion());
            }

            if (Utf8.isWellFormed(data)) {
                return new FunctionState(key, new String(data, UTF_8), null, number, value.getVersion());

View on GitHub (pinned to 820761864e)

Solutions

  1. Verify the exact key spelling/case used when the function stored the value.
  2. Confirm the function actually ran and put the key (check function logs / trigger it first).
  3. Query the correct tenant/namespace/function that owns the key.
  4. If data should exist, inspect the BookKeeper table service / state storage for the namespace to check for data loss.

Example fix

// before
GET .../state/Counter  -> key 'Counter' doesn't exist.

// after (matching stored key)
GET .../state/counter
Defensive patterns

Strategy: try-catch

Try / catch

try {
  const state = await getState(tenant, ns, fn, key);
} catch (e) {
  if (e.status === 404 && e.message.includes("doesn't exist")) {
    // key absent: treat as default/zero or wait until the function writes it
    return defaultValue;
  }
  throw e;
}

Prevention

When it happens

Trigger: GET .../functions/{tenant}/{namespace}/{functionName}/state/{key} where store.getStateValue(key) returns null — the key was never written, has expired/been deleted, or the query targets the wrong function's store.

Common situations: Reading a counter before the function ever incremented it; key-name case mismatch (state keys are case-sensitive); querying a different function instance's key; bookkeeper table-service data loss or store re-created.

Related errors


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