{"record":{"id":"a59af9b8c14010ef","repo":"antlr/antlr4","slug":"unbuffered-stream-cannot-know-its-size","errorCode":null,"errorMessage":"Unbuffered stream cannot know its size","messagePattern":"Unbuffered stream cannot know its size","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"runtime/Java/src/org/antlr/v4/runtime/UnbufferedCharStream.java","lineNumber":310,"sourceCode":"\t\t}\n\t\telse if (i >= n) {\n            throw new UnsupportedOperationException(\"seek to index outside buffer: \"+\n                    index+\" not in \"+getBufferStartIndex()+\"..\"+(getBufferStartIndex()+n));\n        }\n\n\t\tp = i;\n\t\tcurrentCharIndex = index;\n\t\tif (p == 0) {\n\t\t\tlastChar = lastCharBufferStart;\n\t\t}\n\t\telse {\n\t\t\tlastChar = data[p-1];\n\t\t}\n    }\n\n    @Override\n    public int size() {\n        throw new UnsupportedOperationException(\"Unbuffered stream cannot know its size\");\n    }\n\n    @Override\n    public String getSourceName() {\n\t\tif (name == null || name.isEmpty()) {\n\t\t\treturn UNKNOWN_SOURCE_NAME;\n\t\t}\n\n\t\treturn name;\n\t}\n\n\t@Override\n\tpublic String getText(Interval interval) {\n\t\tif (interval.a < 0 || interval.b < interval.a - 1) {\n\t\t\tthrow new IllegalArgumentException(\"invalid interval\");\n\t\t}\n\n\t\tint bufferStartIndex = getBufferStartIndex();","sourceCodeStart":292,"sourceCodeEnd":328,"githubUrl":"https://github.com/antlr/antlr4/blob/7d5770395bb7b02eb56e7c62662cb1d7c08f42a3/runtime/Java/src/org/antlr/v4/runtime/UnbufferedCharStream.java#L292-L328","documentation":"UnbufferedCharStream.size() always throws UnsupportedOperationException because the stream deliberately does not retain the whole input, so total length is unknown until everything is read. This is a design property of the unbuffered streams for processing huge inputs in constant memory, not a transient failure.","triggerScenarios":"Calling size() directly; generic code (progress bars, percent parsers, progress calculations) that calls size() on any IntStream; library utilities that size the input for buffer allocation.","commonSituations":"Sharing code between ANTLRInputStream (where size() works) and UnbufferedCharStream; estimating parse progress; third-party helpers assuming a complete CharStream.","solutions":["Use ANTLRInputStream / CharStreams.fromPath (buffered) when you need size()","Pre-compute the length yourself (file length, or a counting pass) and pass it alongside the stream","Gate size()-dependent logic on the stream type before calling it"],"exampleFix":"// before\nlong pct = 100L * stream.index() / stream.size(); // throws\n\n// after\nlong total = file.length(); // known out-of-band for file input\nlong pct = 100L * stream.index() / total;\n// or use a buffered stream when total size is needed:\nCharStream cs = CharStreams.fromPath(path); // size() now works","handlingStrategy":"fallback","validationCode":"if (stream instanceof UnbufferedCharStream) {\n    long total = knownInputLength; // e.g., file.length(), supplied out-of-band\n    use(total);\n} else {\n    use(stream.size()); // buffered streams support size()\n}","typeGuard":"static boolean supportsSize(CharStream s) {\n    return !(s instanceof UnbufferedCharStream);\n}","tryCatchPattern":null,"preventionTips":["Pick the stream type by feature needs: unbuffered for memory, buffered for size()/random access","Supply input length out-of-band (file size, counting reader) when progress reporting is required","Encapsulate size() calls behind one helper you can fix once"],"tags":["antlr","char-stream","size","unsupported-operation","memory"],"backgroundTag":null,"analyzedSha":"7d5770395bb7b02eb56e7c62662cb1d7c08f42a3","analyzedAt":"2026-08-14T14:47:56.354Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}