{"record":{"id":"b3d503879a00231d","repo":"apache/cassandra","slug":"s-writer-already-finished","errorCode":null,"errorMessage":"[%s] Writer already finished!","messagePattern":"\\[(.+?)\\] Writer already finished!","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/java/org/apache/cassandra/index/sai/disk/v1/bitpack/AbstractBlockPackedWriter.java","lineNumber":122,"sourceCode":"        while ((i & ~0x7FL) != 0L && k++ < 8)\n        {\n            out.writeByte((byte) ((i & 0x7FL) | 0x80L));\n            i >>>= 7;\n        }\n        out.writeByte((byte) i);\n    }\n\n    private void flush() throws IOException\n    {\n        flushBlock();\n        blockIndex = 0;\n    }\n\n    private void checkNotFinished()\n    {\n        if (finished)\n        {\n            throw new IllegalStateException(String.format(\"[%s] Writer already finished!\", indexOutput.getName()));\n        }\n    }\n}\n","sourceCodeStart":104,"sourceCodeEnd":126,"githubUrl":"https://github.com/apache/cassandra/blob/88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1/src/java/org/apache/cassandra/index/sai/disk/v1/bitpack/AbstractBlockPackedWriter.java#L104-L126","documentation":"AbstractBlockPackedWriter guards against writing to a block-packed writer after finish() has been called. Once finished, the block footer/counts are flushed to the IndexOutput, so any further add() (or a second finish()) would corrupt the written file. The exception names the underlying index output file to make the offending component identifiable.","triggerScenarios":"Calling add() after finish() on the same writer, or calling finish() twice; happens when a segment write loop keeps posting rows after the writer was closed out, e.g. double-flush in a segment builder.","commonSituations":"Bugs in SAI segment builders that finish writers early on empty segments or on flush/replay paths, then attempt more writes; internal Cassandra code, not user-triggered directly.","solutions":["Do not call add() after finish(); restructure the write loop so all values are added before finish().","Guard call sites with a finished flag or assert !writer.isFinished() before adding.","If triggered by an internal flush bug, verify against the Cassandra version and check for known SAI segment-builder fixes; upgrade."],"exampleFix":"// before\nwriter.add(value);\nwriter.finish();\nwriter.add(more); // throws\n// after\nwriter.add(value);\nwriter.add(more);\nwriter.finish();","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"boolean canWrite(AbstractBlockPackedWriter w) { return !w.isFinished(); }","tryCatchPattern":"try { writer.add(v); } catch (IllegalStateException e) { log.error(\"Write after finish\", e); throw e; }","preventionTips":["Centralize writer lifecycle: one code path owns add/finish ordering.","Assert writer not finished in debug builds before add()."],"tags":["cassandra","sai","illegal-state","writer-lifecycle"],"backgroundTag":"invalid-state-transition","analyzedSha":"88fd0f6a0eaed8943f05ac9e8f947882b8ddc8f1","analyzedAt":"2026-09-10T07:29:22.284Z","contentChangedAt":"2026-09-10T07:29:22.284Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}