BoundaryML/baml · error · StrongAstError

Expected token/node of kind {expected:?}, but found {found:?

Error message

Expected token/node of kind {expected:?}, but found {found:?} at {at:?}

What it means

StrongAstError::UnexpectedKind is raised by the baml_fmt CST-to-strong-AST conversion (FromCST) when a parser step expects a token or node of a specific SyntaxKind but encounters a different kind at a given TextRange. The error carries the expected kind, the found kind, and the source range, enabling precise diagnostics for malformed or unsupported syntax trees fed to the formatter's AST builder.

Source

Thrown at baml_language/crates/baml_fmt/src/ast/mod.rs:44

};

pub trait FromCST: Sized {
    fn from_cst(elem: SyntaxElement) -> Result<Self, StrongAstError>;
}

/// This AST node only ever has exactly one [`SyntaxKind`].
///
/// Helps with conveniently printing error messages.
pub trait KnownKind {
    /// Should be constant, but we can't use `const` because it's a trait.
    fn kind() -> SyntaxKind;
}

/// Errors that can occur when parsing from a [`SyntaxNode`] with [`FromCST`].
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
pub enum StrongAstError {
    /// When an element is expected (of a specific [`SyntaxKind`]) but was found to be of a different kind.
    #[error("Expected token/node of kind {expected:?}, but found {found:?} at {at:?}")]
    UnexpectedKind {
        expected: SyntaxKind,
        found: SyntaxKind,
        at: TextRange,
    },
    /// When an element is expected but was found to be of a different kind.
    #[error("Expected token/node {expected_desc}, but found {found:?} at {at:?}")]
    UnexpectedKindDesc {
        expected_desc: Cow<'static, str>,
        found: SyntaxKind,
        at: TextRange,
    },
    /// When an element is expected (of a specific [`SyntaxKind`]) but there were no more children left.
    #[error("Expected token/node of kind {expected:?}, but was unable to find it in {parent:?}")]
    MissingExpectedElement {
        expected: SyntaxKind,
        parent: TextRange,
    },

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Look at `at` (TextRange) in the message and inspect the source text there; fix the BAML syntax at that location
  2. Verify the input file parses cleanly with the parser before running the formatter (check for parse errors)
  3. Ensure the baml_fmt and parser crate versions match (grammar drift between versions causes kind mismatches)
  4. If the tree is built/mutated programmatically, validate child kinds before conversion
Defensive patterns

Strategy: validation

Validate before calling

// before converting, verify the child kind at the expected position
let child = parent.first_child_or_token().ok_or("no children")?;
if child.kind() != expected_kind {
    return Err(format!("kind mismatch at {:?}: {:?}", child.text_range(), child.kind()));
}

Type guard

fn is_kind(e: &SyntaxElement, k: SyntaxKind) -> bool { e.kind() == k }

Try / catch

match StrongAst::from_cst(node) {
    Ok(ast) => use(ast),
    Err(StrongAstError::UnexpectedKind { expected, found, at }) => {
        report(at, format!("expected {expected:?}, found {found:?}"));
    }
    Err(e) => report_all(e),
}

Prevention

When it happens

Trigger: Calling FromCST conversion (via the formatter pipeline: parse -> strong AST) on a SyntaxNode whose child at the position the converter expects has a different SyntaxKind — i.e. the CST produced by the parser does not match the grammar the AST builder assumes.

Common situations: Feeding a node of the wrong kind into a strong-AST conversion helper; parser bug or grammar change leaving an unexpected token where the builder expects another; hand-built or mutated syntax trees passed to baml_fmt; formatter run on a file from a newer BAML syntax version.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12). Data as JSON: /api/errors/cd18dc3e2a9d061a. Report an issue: GitHub.