{"record":{"id":"cfe7a55ee26b5d2b","repo":"prestodb/presto","slug":"field-block-builder-has-been-returned","errorCode":null,"errorMessage":"field block builder has been returned","messagePattern":"field block builder has been returned","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"presto-common/src/main/java/com/facebook/presto/common/block/SingleRowBlockWriter.java","lineNumber":220,"sourceCode":"        else {\n            checkFieldIndexToWrite();\n            fieldBlockBuilders[currentFieldIndexToWrite].readPositionFrom(input);\n            entryAdded();\n        }\n        return this;\n    }\n\n    private void entryAdded()\n    {\n        isEntryOpen = false;\n        currentFieldIndexToWrite++;\n    }\n\n    @Override\n    public int getPositionCount()\n    {\n        if (fieldBlockBuilderReturned) {\n            throw new IllegalStateException(\"field block builder has been returned\");\n        }\n        return currentFieldIndexToWrite;\n    }\n\n    @Override\n    public String getEncodingName()\n    {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public Block build()\n    {\n        throw new UnsupportedOperationException();\n    }\n\n    @Override\n    public BlockBuilder newBlockBuilderLike(BlockBuilderStatus blockBuilderStatus)","sourceCodeStart":202,"sourceCodeEnd":238,"githubUrl":"https://github.com/prestodb/presto/blob/55bb57d202de3b926896fa966c2c4a44c779634e/presto-common/src/main/java/com/facebook/presto/common/block/SingleRowBlockWriter.java#L202-L238","documentation":"SingleRowBlockWriter.getPositionCount returns the number of sequential entries written so far. Once getFieldBlockBuilder has been called the writer switches to field-builder mode, so the sequential position count is meaningless; the library throws IllegalStateException instead of returning a misleading value.","triggerScenarios":"Calling getPositionCount() on a SingleRowBlockWriter after getFieldBlockBuilder() was invoked (fieldBlockBuilderReturned == true). Notably the auto-generated toString() implementation calls getPositionCount, so even debugging/logging the writer after switching modes triggers this.","commonSituations":"Developers logging the writer (toString) for debugging after obtaining a field block builder; code paths that inspect progress via getPositionCount in mixed-mode serializers.","solutions":["Do not call getPositionCount (including via toString/logging) after getFieldBlockBuilder has been called.","Track write progress yourself in caller code when in field-builder mode.","Call getPositionCount before obtaining any field block builder, or after the row is fully built via a fresh writer."],"exampleFix":"// before\nBlockBuilder f = writer.getFieldBlockBuilder(0);\nLOG.debug(\"state: \" + writer); // toString -> getPositionCount -> throws\n// after\nLOG.debug(\"positions: \" + writer.getPositionCount()); // before getFieldBlockBuilder\nBlockBuilder f = writer.getFieldBlockBuilder(0);","handlingStrategy":"try-catch","validationCode":"if (fieldBlockBuilderReturned) { /* do not call getPositionCount; track progress in caller */ }","typeGuard":null,"tryCatchPattern":"try {\n    int n = writer.getPositionCount();\n} catch (IllegalStateException e) {\n    // writer switched to field-builder mode; use caller-side counters\n}","preventionTips":["Never log SingleRowBlockWriter with toString after getFieldBlockBuilder","Track written-field counts in serializer code instead of querying the writer","Inspect writer state only before switching write modes"],"tags":["presto","block-builder","illegal-state","tostring"],"backgroundTag":"block-builder-write-mode-conflict","analyzedSha":"55bb57d202de3b926896fa966c2c4a44c779634e","analyzedAt":"2026-09-04T12:50:26.162Z","contentChangedAt":"2026-09-04T12:50:26.162Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}