{"record":{"id":"691067b34a3db586","repo":"clojure/clojure","slug":"eof-while-reading-starting-at-line-691067","errorCode":null,"errorMessage":"EOF while reading, starting at line {}","messagePattern":"EOF while reading, starting at line (.+?)","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/jvm/clojure/lang/LispReader.java","lineNumber":1408,"sourceCode":"\npublic static List readDelimitedList(char delim, PushbackReader r, boolean isRecursive, Object opts, Object pendingForms) {\n\tfinal int firstline =\n\t\t\t(r instanceof LineNumberingPushbackReader) ?\n\t\t\t((LineNumberingPushbackReader) r).getLineNumber() : -1;\n\n\tArrayList a = new ArrayList();\n\tResolver resolver = (Resolver) RT.READER_RESOLVER.deref();\n\n\tfor(; ;) {\n\n\t\tObject form = read(r, false, READ_EOF, delim, READ_FINISHED, isRecursive, opts, pendingForms,\n                           resolver);\n\n\t\tif (form == READ_EOF) {\n\t\t\tif (firstline < 0)\n\t\t\t\tthrow Util.runtimeException(\"EOF while reading\");\n\t\t\telse\n\t\t\t\tthrow Util.runtimeException(\"EOF while reading, starting at line \" + firstline);\n\t\t} else if (form == READ_FINISHED) {\n\t\t\treturn a;\n\t\t}\n\n\t\ta.add(form);\n\t}\n}\n\npublic static class CtorReader extends AFn{\n\tpublic Object invoke(Object reader, Object firstChar, Object opts, Object pendingForms){\n\t\tPushbackReader r = (PushbackReader) reader;\n\t\tpendingForms = ensurePending(pendingForms);\n\t\tObject name = read(r, true, null, false, opts, pendingForms);\n\t\tif (!(name instanceof Symbol))\n\t\t\tthrow new RuntimeException(\"Reader tag must be a symbol\");\n\t\tSymbol sym = (Symbol)name;\n\t\tObject form = read(r, true, null, true, opts, pendingForms);\n","sourceCodeStart":1390,"sourceCodeEnd":1426,"githubUrl":"https://github.com/clojure/clojure/blob/f3b143341d6efc6428b523b2eaa099a6cc99156e/src/jvm/clojure/lang/LispReader.java#L1390-L1426","documentation":"Same condition as \"EOF while reading\" — input ended while a form or delimited list was still open — but the reader knows the line where the form began (firstline >= 0), so the exception includes that line to help locate the truncation.","triggerScenarios":"Reading from a LineNumberingPushbackReader (e.g. load-file/REPL) where input ends before the form started at `firstline` is closed: \"(defn f []\" followed by EOF.","commonSituations":"Source files with a missing final closing paren; loading a namespace file truncated by a failed save; slurp'd config/data files cut short.","solutions":["Go to the reported starting line and balance the delimiters from there","Use a paren-matching editor/parinfer to find the unclosed collection","Verify the file wasn't truncated (compare size/checksum or re-export it)"],"exampleFix":"// before (file cut at line 3)\n(defn f [x]\n  (+ x 1)\n// after\n(defn f [x]\n  (+ x 1))","handlingStrategy":"try-catch","validationCode":"// Clojure: scan a file for balanced delimiters before load\n(defn file-balanced? [f]\n  (let [s (slurp f)]\n    (zero? (reduce (fn [n c] (({\\( inc \\) dec \\[ inc \\] dec \\{ inc \\} dec} c identity) n)) 0 s))))","typeGuard":null,"tryCatchPattern":"// Clojure\n(try\n  (load-file \"src/foo.clj\")\n  (catch RuntimeException e\n    (if (re-find #\"EOF while reading, starting at line (\\d+)\" (.getMessage e))\n      (report-truncated-file e)\n      (throw e))))","preventionTips":["Parse the reported line number from the message to jump straight to the unclosed form","Use parinfer or a paren-matching editor for source files","Confirm file saves completed (size changed) before loading"],"tags":["clojure","reader","eof","truncated-input"],"backgroundTag":"unexpected-eof","analyzedSha":"f3b143341d6efc6428b523b2eaa099a6cc99156e","analyzedAt":"2026-09-09T12:04:58.961Z","contentChangedAt":"2026-09-09T12:04:58.961Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}