{"record":{"id":"4010ff5ae44386f4","repo":"zed-industries/zed","slug":"should-have-an-extension","errorCode":null,"errorMessage":"{} should have an extension","messagePattern":"(.+?) should have an extension","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/edit_prediction_cli/src/example.rs","lineNumber":234,"sourceCode":"    let mut examples = Vec::new();\n\n    for path in inputs {\n        let is_stdin = path.as_path() == Path::new(\"-\");\n        let content = if is_stdin {\n            let mut buffer = String::new();\n            std::io::stdin()\n                .read_to_string(&mut buffer)\n                .expect(\"Failed to read from stdin\");\n            buffer\n        } else {\n            std::fs::read_to_string(path)\n                .unwrap_or_else(|_| panic!(\"Failed to read path: {path:?}\"))\n        };\n        let filename = path.file_stem().unwrap().to_string_lossy().to_string();\n        let ext = if !is_stdin {\n            path.extension()\n                .map(|ext| ext.to_string_lossy().to_string())\n                .unwrap_or_else(|| panic!(\"{} should have an extension\", path.display()))\n        } else {\n            \"jsonl\".to_string()\n        };\n\n        match ext.as_ref() {\n            \"json\" => {\n                let mut example =\n                    serde_json::from_str::<Example>(&content).unwrap_or_else(|error| {\n                        panic!(\"Failed to parse example file: {}\\n{error}\", path.display())\n                    });\n                if example.spec.name.is_empty() {\n                    example.spec.name = filename;\n                }\n                examples.push(example);\n            }\n            \"jsonl\" => examples.extend(\n                content\n                    .lines()","sourceCodeStart":216,"sourceCodeEnd":252,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/edit_prediction_cli/src/example.rs#L216-L252","documentation":"For non-stdin inputs the loader derives the parser from the file extension: .json parses one Example object, .jsonl parses line-delimited records. A path with no extension reaches a panic stating the file must carry one. Stdin ('-') defaults to jsonl, which is why piped input bypasses the check.","triggerScenarios":"Passing a file named without a suffix ('examples', 'input'); temp files created via mktemp without an extension; shell variables where the extension was accidentally stripped during string manipulation.","commonSituations":"Renamed downloads losing extensions; artifacts written by scripts that omit suffixes; copy-paste of example commands with truncated names.","solutions":["Rename the file with .json or .jsonl","Or pipe it via stdin: cat file | edit-prediction-cli eval -","Fix the producer script so generated files always carry an extension"],"exampleFix":"# before\nedit-prediction-cli eval inputs   # panic: inputs should have an extension\n\n# after\nmv inputs inputs.jsonl\nedit-prediction-cli eval inputs.jsonl","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\nsuffix = Path(path).suffix\nassert suffix in {\".json\", \".jsonl\"}, f\"{path} must end in .json or .jsonl (or pipe it via '-')\"","typeGuard":"import pathlib\n\ndef has_example_extension(path: str) -> bool:\n    return pathlib.Path(path).suffix in {\".json\", \".jsonl\"}","tryCatchPattern":null,"preventionTips":["Make producer scripts always write .json/.jsonl suffixes","Pipe extension-less files through stdin instead of renaming ad hoc","Check mv/cp commands in scripts for accidentally truncated names"],"tags":["cli","file-extension","panic","edit-prediction"],"backgroundTag":"missing-file-extension","analyzedSha":"f4178619acd0d47ea1f76a2025c42962c6d6638c","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}