{"record":{"id":"56d6e1d821aa2930","repo":"apache/druid","slug":"dictionary-not-serialized-cannot-open-value-seria-56d6e1","errorCode":null,"errorMessage":"Dictionary not serialized, cannot open value serializer","messagePattern":"Dictionary not serialized, cannot open value serializer","errorType":"exception","errorClass":"java.lang.IllegalStateException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/segment/nested/VariantColumnSerializer.java","lineNumber":186,"sourceCode":"    arrayElementDictionaryWriter = new FixedIndexedIntWriter(segmentWriteOutMedium, true);\n    arrayElementDictionaryWriter.open();\n    dictionaryIdLookup = closer.register(\n        new DictionaryIdLookup(\n            name,\n            segmentBaseDir,\n            dictionaryWriter,\n            longDictionaryWriter,\n            doubleDictionaryWriter,\n            arrayDictionaryWriter\n        )\n    );\n  }\n\n  @Override\n  public void open() throws IOException\n  {\n    if (!dictionarySerialized) {\n      throw new IllegalStateException(\"Dictionary not serialized, cannot open value serializer\");\n    }\n    intermediateValueWriter = new FixedIndexedIntWriter(segmentWriteOutMedium, false);\n    intermediateValueWriter.open();\n  }\n\n  @Override\n  public void serializeDictionaries(\n      Iterable<String> strings,\n      Iterable<Long> longs,\n      Iterable<Double> doubles,\n      Iterable<int[]> arrays\n  ) throws IOException\n  {\n    if (dictionarySerialized) {\n      throw new ISE(\"Value dictionaries already serialized for column [%s], cannot serialize again\", name);\n    }\n\n    // null is always 0","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/nested/VariantColumnSerializer.java#L168-L204","documentation":"VariantColumnSerializer.open() initializes the intermediate value writer, but this is only legal after the value dictionaries have been serialized (dictionarySerialized == true). Calling open() beforehand leaves the serializer in an unusable state, so it throws IllegalStateException 'Dictionary not serialized, cannot open value serializer'.","triggerScenarios":"Calling open() before serializeDictionaries() during segment merge (smooshify), or a merge code path that invokes open out of order.","commonSituations":"Custom segment merge/compression tooling that calls the writer lifecycle methods in the wrong order; Druid internal bugs in segment merge tasks.","solutions":["Call serializeDictionaries() before open() in the writer lifecycle","Follow the standard serializer contract: open the dictionary writer, serialize dictionaries, then open the value writer","Upgrade Druid if a merge task triggers this through an internal bug","Review any custom ColumnSerializer subclass for out-of-order lifecycle calls"],"exampleFix":"// before\nserializer.open();\nserializer.serializeDictionaries(strings, longs, doubles, arrays);\n// after\nserializer.serializeDictionaries(strings, longs, doubles, arrays);\nserializer.open();","handlingStrategy":"validation","validationCode":"if (!serializer.isDictionarySerialized()) { serializer.serializeDictionaries(strings, longs, doubles, arrays); } serializer.open();","typeGuard":null,"tryCatchPattern":"try { serializer.open(); } catch (IllegalStateException e) { if (e.getMessage().contains(\"Dictionary not serialized\")) { /* fix lifecycle order and retry with a fresh serializer */ } throw e; }","preventionTips":["Follow the documented writer lifecycle: serializeDictionaries -> open -> serialize","Unit-test custom merge tooling lifecycle order","Wrap lifecycle steps in a single orchestrating method"],"tags":["druid","segment-writing","lifecycle"],"backgroundTag":"invalid-state-transition","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}