apache/pulsar · warning · RestException

Path key doesn't match key in json

Error message

Path key doesn't match key in json

What it means

putFunctionState requires that the state key in the URL path exactly equals the "key" field of the JSON body. On mismatch the worker throws a 400 RestException "Path key doesn't match key in json". This prevents writing state under a different key than the request advertises.

Source

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

                                 final FunctionState state,
                                 final AuthenticationParameters authParams) {

        if (!isWorkerServiceAvailable()) {
            throwUnavailableException();
        }

        if (null == worker().getStateStoreProvider()) {
            throwStateStoreUnvailableResponse();
        }

        throwRestExceptionIfUnauthorizedForNamespace(tenant, namespace, functionName, "put state for",
                authParams);

        if (!key.equals(state.getKey())) {
            log.error().attr("tenant", tenant).attr("namespace", namespace).attr("componentName", functionName)

                    .log("/ / Bad putFunction Request, path key doesn't match key in json");
            throw new RestException(Status.BAD_REQUEST, "Path key doesn't match key in json");
        }

        // validate parameters
        try {
            validateFunctionStateParams(tenant, namespace, functionName, key);
        } catch (IllegalArgumentException e) {
            log.error().attr("tenant", tenant).attr("namespace", namespace).attr("componentName", functionName)

                    .attr("key", key).exception(e).log("Invalid putFunctionState 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("putFunctionState does not exist @ / / /");
            throw new RestException(Status.NOT_FOUND, String.format("'%s' is not found", functionName));

View on GitHub (pinned to 820761864e)

Solutions

  1. Make the JSON body's "key" field identical to the {key} path segment.
  2. If using a client/helper, build both URL and body from the same key variable.
  3. Log the request body before sending to confirm the key field value.

Example fix

// before
curl -X PUT .../state/counter -d '{"key":"count","stringValue":"1"}'

// after
curl -X PUT .../state/counter -d '{"key":"counter","stringValue":"1"}'
Defensive patterns

Strategy: validation

Validate before calling

// Ensure body key matches path key before sending
function putStateRequest(pathKey, state) {
  if (state.key !== pathKey) {
    throw new Error(`Body key '${state.key}' must equal path key '${pathKey}'`);
  }
  return doPut(pathKey, state);
}

Type guard

function keysMatch(pathKey, state) { return state != null && typeof state.key === 'string' && state.key === pathKey; }

Try / catch

try {
  await putState(tenant, ns, fn, key, body);
} catch (e) {
  if (e.status === 400 && e.message.includes("Path key doesn't match")) {
    // rebuild request with body.key = key and retry once
  } else throw e;
}

Prevention

When it happens

Trigger: PUT .../functions/{tenant}/{namespace}/{functionName}/state/{pathKey} with a FunctionState JSON body whose "key" field differs from {pathKey}, e.g. path says 'counter' but body contains "key":"counters".

Common situations: Hand-built curl payloads where the body key was edited but the URL was not; clients that derive the path from one variable and the body from another; copy-paste of example payloads without updating both places.

Related errors


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