biomejs/biome · error

found a token with no parent

Error message

found a token with no parent

What it means

Panic in the CSS format-on-type handler (css.rs:662). After locating the token under the cursor via token_at_offset, the code calls token.parent(); in a rowan syntax tree the root is always a node, so a token retrieved from token_at_offset normally always has a parent. This branch is a defensive assertion that fires only if the token is detached or the tree root were a bare token - states that should not occur for tokens produced by the parser.

Solutions

  1. Update to the latest Biome patch release in case the branch was removed or the underlying parse issue fixed
  2. Capture a minimal document plus keystroke that reproduces it and file an issue at https://github.com/biomejs/biome/issues
  3. If you embed biome_service, run the workspace inside catch_unwind so an on-type panic degrades to 'no formatting' instead of taking down the host
Defensive patterns

Strategy: fallback

Try / catch

// LSP client - degrade gracefully if the server dies on an on-type request
try {
  const edits = await client.sendRequest('textDocument/onTypeFormatted', params);
} catch {
  // formatting failed server-side; leave the buffer untouched instead of surfacing an error
}

Prevention

When it happens

Trigger: Effectively unreachable through normal LSP traffic: any token returned by tree.token_at_offset(offset) belongs to the tree and has a parent node. Would only fire through API misuse (passing a detached token) or an exotic parse producing a token-rooted tree.

Common situations: Almost never seen in practice; appears in crash reports only alongside corrupted or hand-constructed syntax trees, or after internal refactors of the parser.

Related errors


AI-assisted analysis of biomejs/biome@17a2560fb5 (2026-08-20). Data as JSON: /api/errors/fd26fe59124d3566. Report an issue: GitHub.

Appendix: source

Thrown at crates/biome_service/src/file_handlers/css.rs:661

        // File is empty, do nothing
        TokenAtOffset::None => panic!("empty file"),
        TokenAtOffset::Single(token) => token,
        // The cursor should be right after the closing character that was just typed,
        // select the previous token as the correct one
        TokenAtOffset::Between(token, _) => token,
    };

    if token.text_trimmed_range().end() != offset {
        return Ok(format_on_type_noop(offset));
    }

    if !matches_on_type_char(token.text_trimmed()) {
        return Ok(format_on_type_noop(offset));
    }

    let root_node = match token.parent() {
        Some(node) => node,
        None => panic!("found a token with no parent"),
    };

    if root_node
        .ancestors()
        .any(|node: CssSyntaxNode| node.kind().is_bogus())
    {
        return Ok(format_on_type_noop(offset));
    }

    let printed =
        biome_css_formatter::format_range(options, &tree, root_node.text_trimmed_range())?;
    Ok(printed)
}

fn lint(params: LintParams) -> LintResults {
    let Some(file_source) = params.language.to_css_file_source() else {
        return LintResults {
            diagnostics: vec![],

View on GitHub (pinned to 17a2560fb5)