{"id":"4c28d960b4621434","repo":"apache/kafka","slug":"key-cannot-be-null","errorCode":null,"errorMessage":"key cannot be null.","messagePattern":"key cannot be null\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"clients/src/main/java/org/apache/kafka/common/header/internals/RecordHeaders.java","lineNumber":126,"sourceCode":"    public Iterator<Header> iterator() {\n        return closeAware(headers.iterator());\n    }\n\n    public void setReadOnly() {\n        this.isReadOnly = true;\n    }\n\n    public boolean isReadOnly() {\n        return isReadOnly;\n    }\n\n    public Header[] toArray() {\n        return headers.isEmpty() ? Record.EMPTY_HEADERS : headers.toArray(new Header[0]);     \n    }\n\n    private void checkKey(String key) {\n        if (key == null)\n            throw new IllegalArgumentException(\"key cannot be null.\");\n    }\n\n    private void canWrite() {\n        if (isReadOnly)\n            throw new IllegalStateException(\"RecordHeaders has been closed.\");\n    }\n\n    private Iterator<Header> closeAware(final Iterator<Header> original) {\n        return new Iterator<>() {\n            @Override\n            public boolean hasNext() {\n                return original.hasNext();\n            }\n\n            public Header next() {\n                return original.next();\n            }\n","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/apache/kafka/blob/c31c9215e131f8c17e79f8901b48c13ee6aa8e7a/clients/src/main/java/org/apache/kafka/common/header/internals/RecordHeaders.java#L108-L144","documentation":"Thrown as IllegalArgumentException by RecordHeaders.checkKey(String) when a null key is passed to lastHeader(key), headers(key), or remove(key). RecordHeaders stores headers keyed by String and uses equals comparisons on keys in iteration, so a null key would both NPE during comparison and is rejected as a programmer error at entry. The guard runs before any iteration, failing fast.","triggerScenarios":"Calling record.headers().lastHeader(null), .headers(null), or .remove(null); passing a header key sourced from a variable that was never initialized or came from a null-producing mapping (e.g. a missing field in an upstream POJO mapped to header keys).","commonSituations":"Producer interceptor / serializer that converts POJO fields to headers but does not null-check field values; copy-paste of a header key constant that was renamed and now resolves to null; reactive pipeline where a null key slips through from a malformed input record.","solutions":["Null-check the key before calling lastHeader/headers/remove, and decide explicitly whether to skip the header or throw a domain error.","Trace the source of the key variable; if it comes from a POJO/mapping, fix the upstream mapping to never yield null for header keys.","If iterating headers with a filter, prefer iterator() and filter by a non-null constant.","Add a unit test that asserts the producer path never passes null keys (e.g. via a recording interceptor)."],"exampleFix":"// before\nString traceId = span.context().traceId();   // may be null\nheaders.lastHeader(traceId);\n\n// after\nString traceId = span.context().traceId();\nif (traceId != null) {\n    headers.lastHeader(traceId);\n}","handlingStrategy":"validation","validationCode":"String key = ...;\nif (key == null) {\n    throw new IllegalArgumentException(\"header key must not be null\");\n}\nheaders.lastHeader(key); // or remove(key) / headers(key)","typeGuard":"static String requireHeaderKey(String key) {\n    if (key == null) throw new IllegalArgumentException(\"header key must not be null\");\n    return key;\n}","tryCatchPattern":"try {\n    headers.remove(key);\n} catch (IllegalArgumentException e) {\n    // message: \"key cannot be null.\"\n    // caller passed a null header key; fix the upstream source of the key\n}","preventionTips":["Centralize header-key construction so nulls never reach the Headers API","Never use Optional.orElse(null) to produce a header key","Reject null keys at the boundary where headers are produced (e.g. your serialization layer)","Prefer Map entries or records with non-null key types when building headers"],"tags":["headers","producer","validation","illegal-argument"],"analyzedSha":"c31c9215e131f8c17e79f8901b48c13ee6aa8e7a","analyzedAt":"2026-08-03T12:34:05.770Z","schemaVersion":2}