{"record":{"id":"623e23b53c8e13e7","repo":"apache/pulsar","slug":"path-key-doesn-t-match-key-in-json","errorCode":null,"errorMessage":"Path key doesn't match key in json","messagePattern":"Path key doesn't match key in json","errorType":"http","errorClass":"RestException","httpStatus":400,"severity":"warning","filePath":"pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/ComponentImpl.java","lineNumber":1331,"sourceCode":"                                 final FunctionState state,\n                                 final AuthenticationParameters authParams) {\n\n        if (!isWorkerServiceAvailable()) {\n            throwUnavailableException();\n        }\n\n        if (null == worker().getStateStoreProvider()) {\n            throwStateStoreUnvailableResponse();\n        }\n\n        throwRestExceptionIfUnauthorizedForNamespace(tenant, namespace, functionName, \"put state for\",\n                authParams);\n\n        if (!key.equals(state.getKey())) {\n            log.error().attr(\"tenant\", tenant).attr(\"namespace\", namespace).attr(\"componentName\", functionName)\n\n                    .log(\"/ / Bad putFunction Request, path key doesn't match key in json\");\n            throw new RestException(Status.BAD_REQUEST, \"Path key doesn't match key in json\");\n        }\n\n        // validate parameters\n        try {\n            validateFunctionStateParams(tenant, namespace, functionName, key);\n        } catch (IllegalArgumentException e) {\n            log.error().attr(\"tenant\", tenant).attr(\"namespace\", namespace).attr(\"componentName\", functionName)\n\n                    .attr(\"key\", key).exception(e).log(\"Invalid putFunctionState request @ / / / /\");\n            throw new RestException(Status.BAD_REQUEST, e.getMessage());\n        }\n\n        FunctionMetaDataManager functionMetaDataManager = worker().getFunctionMetaDataManager();\n        if (!functionMetaDataManager.containsFunction(tenant, namespace, functionName)) {\n            log.warn().attr(\"tenant\", tenant).attr(\"namespace\", namespace).attr(\"componentName\", functionName)\n\n                    .log(\"putFunctionState does not exist @ / / /\");\n            throw new RestException(Status.NOT_FOUND, String.format(\"'%s' is not found\", functionName));","sourceCodeStart":1313,"sourceCodeEnd":1349,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/ComponentImpl.java#L1313-L1349","documentation":"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.","triggerScenarios":"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\".","commonSituations":"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.","solutions":["Make the JSON body's \"key\" field identical to the {key} path segment.","If using a client/helper, build both URL and body from the same key variable.","Log the request body before sending to confirm the key field value."],"exampleFix":"// before\ncurl -X PUT .../state/counter -d '{\"key\":\"count\",\"stringValue\":\"1\"}'\n\n// after\ncurl -X PUT .../state/counter -d '{\"key\":\"counter\",\"stringValue\":\"1\"}'","handlingStrategy":"validation","validationCode":"// Ensure body key matches path key before sending\nfunction putStateRequest(pathKey, state) {\n  if (state.key !== pathKey) {\n    throw new Error(`Body key '${state.key}' must equal path key '${pathKey}'`);\n  }\n  return doPut(pathKey, state);\n}","typeGuard":"function keysMatch(pathKey, state) { return state != null && typeof state.key === 'string' && state.key === pathKey; }","tryCatchPattern":"try {\n  await putState(tenant, ns, fn, key, body);\n} catch (e) {\n  if (e.status === 400 && e.message.includes(\"Path key doesn't match\")) {\n    // rebuild request with body.key = key and retry once\n  } else throw e;\n}","preventionTips":["Derive both the URL path and the JSON body key from one variable.","Add a client-side assertion that body.key === pathKey before every put.","Avoid hand-editing example payloads in only one of the two places."],"tags":["rest-api","validation","bad-request","state"],"backgroundTag":"request-body-path-mismatch","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}