{"record":{"id":"7cd6295a2278f0c9","repo":"gradle/gradle","slug":"cannot-encode-a-null-string-7cd629","errorCode":null,"errorMessage":"Cannot encode a null string.","messagePattern":"Cannot encode a null string\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"platforms/core-runtime/serialization/src/main/java/org/gradle/internal/serialize/kryo/StringDeduplicatingKryoBackedEncoder.java","lineNumber":110,"sourceCode":"\n    @Override\n    public void writeBoolean(boolean value) {\n        output.writeBoolean(value);\n    }\n\n    @Override\n    public void writeNullableString(@Nullable CharSequence value) {\n        if (value == null) {\n            writeStringIndex(NULL_STRING);\n            return;\n        }\n        writeNonnullString(value);\n    }\n\n    @Override\n    public void writeString(CharSequence value) {\n        if (value == null) {\n            throw new IllegalArgumentException(\"Cannot encode a null string.\");\n        }\n        writeNonnullString(value);\n    }\n\n    private void writeNonnullString(CharSequence value) {\n        String key = value.toString();\n        if (strings == null) {\n            strings = new Object2IntOpenHashMap<>(1024);\n        } else {\n            int index = strings.getOrDefault(key, -1);\n            if (index != -1) {\n                writeStringIndex(index);\n                return;\n            }\n        }\n\n        /*\n          Actual stored string indices start from 2 so `0` and `1` can be used as special codes:","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/gradle/gradle/blob/534f27719b66953f95cc907aae7f2c1b12f5482d/platforms/core-runtime/serialization/src/main/java/org/gradle/internal/serialize/kryo/StringDeduplicatingKryoBackedEncoder.java#L92-L128","documentation":"This encoder deduplicates repeated strings and encodes null via a special NULL_STRING index — but only through writeNullableString. Its writeString still rejects null, because the non-null path writes a dedup index with no null representation.","triggerScenarios":"Calling writeString(null) on the string-deduplicating encoder; forwarding an optional CharSequence field to writeString instead of writeNullableString before dedup lookup.","commonSituations":"Long-lived caches that use string deduplication where optional fields were later introduced; the same class of null-handling mistake as the other encoders, discovered only when the field is actually null at runtime.","solutions":["Route optional strings through writeNullableString(value), which emits the NULL_STRING index.","Or guard and substitute \"\" when empty is an acceptable value.","Remove nulls upstream so the non-null path is always valid."],"exampleFix":"// before\nencoder.writeString(pathOrNull); // throws \"Cannot encode a null string.\"\n\n// after\nencoder.writeNullableString(pathOrNull);","handlingStrategy":"validation","validationCode":"if (value == null) {\n    encoder.writeNullableString(null); // emits NULL_STRING index\n} else {\n    encoder.writeString(value);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Only writeNullableString may encode null on the deduplicating encoder.","When adding optional fields to a deduplicated codec, update writer and reader together.","Re-run dedup cache tests with null values before shipping."],"tags":["gradle","serialization","kryo","null-safety","string-dedup"],"backgroundTag":"null-value-encode","analyzedSha":"534f27719b66953f95cc907aae7f2c1b12f5482d","analyzedAt":"2026-08-22T08:09:12.375Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}