{"record":{"id":"d101a6db2b71920e","repo":"apache/pulsar","slug":"invalid-state-value","errorCode":null,"errorMessage":"Invalid state value","messagePattern":"Invalid state value","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":500,"severity":"error","filePath":"pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/ComponentImpl.java","lineNumber":1362,"sourceCode":"        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));\n        }\n\n        try {\n            DefaultStateStore store = worker().getStateStoreProvider().getStateStore(tenant, namespace, functionName);\n            ByteBuffer data;\n            if (state.getByteValue() == null || state.getByteValue().length == 0) {\n                if (state.getStringValue() != null) {\n                    data = ByteBuffer.wrap(state.getStringValue().getBytes(UTF_8));\n                }  else if (state.getNumberValue() != null) {\n                    data = ByteBuffer.allocate(Long.BYTES);\n                    data.putLong(state.getNumberValue());\n                } else {\n                    throw new IllegalArgumentException(\"Invalid state value\");\n                }\n            } else {\n                data = ByteBuffer.wrap(state.getByteValue());\n            }\n            store.put(key, data);\n        } catch (Throwable e) {\n            log.error().attr(\"tenant\", tenant).attr(\"namespace\", namespace).attr(\"componentName\", functionName)\n\n                    .attr(\"key\", key).exception(e).log(\"Error while putFunctionState request @ / / / /\");\n            throw new RestException(Status.INTERNAL_SERVER_ERROR, e.getMessage());\n        }\n    }\n\n    @Override\n    public void uploadFunction(final InputStream uploadedInputStream, final String path,\n                               AuthenticationParameters authParams) {\n\n        if (!isWorkerServiceAvailable()) {","sourceCodeStart":1344,"sourceCodeEnd":1380,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/worker/src/main/java/org/apache/pulsar/functions/worker/rest/api/ComponentImpl.java#L1344-L1380","documentation":"putFunctionState accepts exactly one of byteValue, stringValue, or numberValue in the FunctionState body. When byteValue is null/empty and neither stringValue nor numberValue is set, the worker throws IllegalArgumentException(\"Invalid state value\"), which the surrounding catch converts to a 500 RestException. The request carried no usable value payload.","triggerScenarios":"PUT .../functions/{tenant}/{namespace}/{functionName}/state/{key} with a body like {\"key\":\"k\"} — byteValue null/empty, stringValue null, numberValue null. Note the 500 status (not 400) because the IllegalArgumentException is caught by the generic Throwable handler.","commonSituations":"Clients serializing FunctionState objects with all value fields unset; JSON field name mismatches (e.g. sending \"value\" instead of \"stringValue\"); base64 byteValue decoded to an empty array on the server; omitting the value when only intending to update a key.","solutions":["Include exactly one value field in the body: stringValue (string), numberValue (long), or byteValue (base64 bytes).","Check field names — the server expects stringValue/numberValue/byteValue, not generic \"value\".","Ensure byteValue base64 decodes to a non-empty byte array if you intend a byte write.","Expect a 500 here despite it being a client payload problem; fix the payload rather than retrying."],"exampleFix":"// before: no value in body -> 500 'Invalid state value'\ncurl -X PUT .../state/counter -d '{\"key\":\"counter\"}'\n\n// after\ncurl -X PUT .../state/counter -d '{\"key\":\"counter\",\"stringValue\":\"42\"}'","handlingStrategy":"validation","validationCode":"// Exactly one value variant must be set\nfunction validStateBody(state) {\n  const set = [!!state.stringValue, state.numberValue != null,\n               Array.isArray(state.byteValue) && state.byteValue.length > 0].filter(Boolean).length;\n  return set === 1 && typeof state.key === 'string' && state.key.length > 0;\n}","typeGuard":"function hasValue(state) {\n  return state != null && (\n    (typeof state.stringValue === 'string') ||\n    (typeof state.numberValue === 'number') ||\n    (Array.isArray(state.byteValue) && state.byteValue.length > 0));\n}","tryCatchPattern":"try {\n  await putState(tenant, ns, fn, key, body);\n} catch (e) {\n  if (e.status === 500 && e.message.includes(\"Invalid state value\")) {\n    // payload problem despite 500: add stringValue/numberValue/byteValue and retry\n  } else throw e;\n}","preventionTips":["Always set exactly one of stringValue, numberValue, or byteValue in the FunctionState body.","Use the exact field names stringValue/numberValue/byteValue in JSON.","Never send an empty byteValue array with no alternative value set.","Remember this condition surfaces as HTTP 500, not 400 — treat matching 500s as payload bugs."],"tags":["rest-api","validation","state","functions"],"backgroundTag":"invalid-state-value","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}