{"record":{"id":"27f7a27cbe240ff8","repo":"biomejs/biome","slug":"empty-file-27f7a2","errorCode":null,"errorMessage":"empty file","messagePattern":"empty file","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/biome_service/src/file_handlers/json.rs","lineNumber":595,"sourceCode":"    settings: &SettingsWithEditor,\n    offset: TextSize,\n    workspace_db: WorkspaceDb,\n) -> Result<Printed, WorkspaceError> {\n    let options = resolve_format_options(document_file_source, settings, &workspace_db);\n\n    let tree = parse.syntax(&workspace_db);\n\n    let range = tree.text_range_with_trivia();\n    if offset < range.start() || offset > range.end() {\n        return Err(WorkspaceError::FormatError(FormatError::RangeError {\n            input: TextRange::at(offset, TextSize::from(0)),\n            tree: range,\n        }));\n    }\n\n    let token = match tree.token_at_offset(offset) {\n        // File is empty, do nothing\n        TokenAtOffset::None => panic!(\"empty file\"),\n        TokenAtOffset::Single(token) => token,\n        // The cursor should be right after the closing character that was just typed,\n        // select the previous token as the correct one\n        TokenAtOffset::Between(token, _) => token,\n    };\n\n    if token.text_trimmed_range().end() != offset {\n        return Ok(format_on_type_noop(offset));\n    }\n\n    if !matches_on_type_char(token.text_trimmed()) {\n        return Ok(format_on_type_noop(offset));\n    }\n\n    let root_node = match token.parent() {\n        Some(node) => node,\n        None => panic!(\"found a token with no parent\"),\n    };","sourceCodeStart":577,"sourceCodeEnd":613,"githubUrl":"https://github.com/biomejs/biome/blob/405dedb0ff65dd29927faf587f6542e3c29db248/crates/biome_service/src/file_handlers/json.rs#L577-L613","documentation":"Panic in the JSON format-on-type handler (json.rs:595). For a textDocument/onTypeFormatted request, Biome locates the token at the cursor via tree.token_at_offset(offset); TokenAtOffset::None means the tree has no tokens, i.e. an empty document. The arm's comment ('File is empty, do nothing') does not match the code, which panics, so on-type formatting an empty JSON document crashes this path.","triggerScenarios":"An LSP client sends onTypeFormatted for a zero-length .json document: offset 0 passes the range guard over tree range 0..0, token_at_offset(0) returns None, and the panic fires.","commonSituations":"Editors firing on-type format on newly created empty JSON files (tsconfig.json, package.json just opened); LSP bots replaying keystrokes into empty buffers.","solutions":["Update Biome and report the panic upstream if it persists (https://github.com/biomejs/biome/issues)","Skip sending textDocument/onTypeFormatted while the document is empty","In a fork: TokenAtOffset::None => return Ok(format_on_type_noop(offset))"],"exampleFix":"// before\nTokenAtOffset::None => panic!(\"empty file\"),\n\n// after\nTokenAtOffset::None => return Ok(format_on_type_noop(offset)),","handlingStrategy":"validation","validationCode":"// LSP client (TypeScript) - skip on-type formatting for empty JSON files\nif (document.getText().length === 0) return;","typeGuard":"const isEmptyDocument = (document: TextDocument): boolean =>\n  document.getText().length === 0;","tryCatchPattern":null,"preventionTips":["Do not send onTypeFormatted for empty .json documents (fresh tsconfig.json/package.json buffers)","Enable format-on-type only after the user types actual content","Track upstream fixes for the empty-file panic"],"tags":["json","lsp","format-on-type","panic","empty-file"],"backgroundTag":"format-on-type-empty-document","analyzedSha":"405dedb0ff65dd29927faf587f6542e3c29db248","analyzedAt":"2026-08-20T00:25:09.682Z","contentChangedAt":"2026-08-20T00:25:09.682Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}