{"record":{"id":"dcb1fc3e29e96ef5","repo":"biomejs/biome","slug":"found-a-token-with-no-parent-dcb1fc","errorCode":null,"errorMessage":"found a token with no parent","messagePattern":"found a token with no parent","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/biome_service/src/file_handlers/json.rs","lineNumber":612,"sourceCode":"        // 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    };\n\n    if root_node\n        .ancestors()\n        .any(|node: JsonSyntaxNode| node.kind().is_bogus())\n    {\n        return Ok(format_on_type_noop(offset));\n    }\n\n    let printed =\n        biome_json_formatter::format_range(options, &tree, root_node.text_trimmed_range())?;\n    Ok(printed)\n}\n\nfn lint(params: LintParams) -> LintResults {\n    let _ = debug_span!(\"Linting JSON file\", path =? params.path, language =? params.language)\n        .entered();\n    let Some(file_source) = params","sourceCodeStart":594,"sourceCodeEnd":630,"githubUrl":"https://github.com/biomejs/biome/blob/405dedb0ff65dd29927faf587f6542e3c29db248/crates/biome_service/src/file_handlers/json.rs#L594-L630","documentation":"Panic in the JSON format-on-type handler (json.rs:612). After locating the token at the cursor, the handler calls token.parent(); tokens returned by token_at_offset on a parsed rowan tree always have a parent node since the root is a node. This is a defensive assertion for detached or token-rooted trees, which the normal parse path cannot produce.","triggerScenarios":"Not reachable through normal LSP requests; only a detached token or a token as tree root would trigger it.","commonSituations":"Effectively theoretical; only plausible with hand-constructed syntax trees or internal API misuse.","solutions":["Update to the latest Biome release","Report a reproducer to https://github.com/biomejs/biome/issues if you can trigger it","Embedders: guard the call with catch_unwind and degrade to no formatting"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"// LSP client - on-type formatting is best-effort\ntry {\n  const edits = await client.sendRequest('textDocument/onTypeFormatted', params);\n} catch {\n  // ignore server-side failure; buffer stays as typed\n}","preventionTips":["Never block user input on onTypeFormatted responses","Pin a known-good Biome build in the editor integration","Report reproductions; this defensive panic should not be reachable"],"tags":["json","lsp","format-on-type","panic","defensive-check"],"backgroundTag":"syntax-token-no-parent","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"}