{"record":{"id":"54e09a13c481553c","repo":"BoundaryML/baml","slug":"expected-a-schema","errorCode":null,"errorMessage":"Expected a schema","messagePattern":"Expected a schema","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/baml-lib/ast/src/formatter/mod.rs","lineNumber":33,"sourceCode":"};\nuse pretty::RcDoc;\nuse regex::Regex;\n\nuse crate::parser::{BAMLParser, Rule};\n\npub struct FormatOptions {\n    pub indent_width: isize,\n    pub fail_on_unhandled_rule: bool,\n}\n\npub fn format_schema(source: &str, format_options: FormatOptions) -> Result<String> {\n    let ignore_directive_regex = Regex::new(r\"(?i)baml-format\\s*:\\s*ignore\")?;\n    if ignore_directive_regex.is_match(source) {\n        return Ok(source.to_string());\n    }\n\n    let mut schema = BAMLParser::parse(Rule::schema, source)?;\n    let schema_pair = schema.next().ok_or(anyhow!(\"Expected a schema\"))?;\n    if schema_pair.as_rule() != Rule::schema {\n        return Err(anyhow!(\"Expected a schema\"));\n    }\n\n    let formatter = Formatter {\n        indent_width: format_options.indent_width,\n        fail_on_unhandled_rule: format_options.fail_on_unhandled_rule,\n    };\n\n    let doc = formatter.schema_to_doc(schema_pair.into_inner())?;\n    let mut w = Vec::new();\n    doc.render(10, &mut w)\n        .map_err(|_| anyhow!(\"Failed to render doc\"))?;\n    String::from_utf8(w).map_err(|_| anyhow!(\"Failed to convert to string\"))\n}\n\nmacro_rules! next_pair {\n    ($pairs:ident, $rule:expr) => {{","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/baml-lib/ast/src/formatter/mod.rs#L15-L51","documentation":"format_schema parses the BAML source with a pest-generated BAMLParser expecting a Rule::schema at the top; schema.next() returned None (empty parse) so the code raises \"Expected a schema\" via ok_or. This means the input could not yield any top-level schema pair — typically empty or unparseable input at the very start of parsing.","triggerScenarios":"Calling format_schema / the formatter (baml-cli format, format_document, assert_format_eq) with an empty string, whitespace-only input, or input that pest cannot match as a schema at all.","commonSituations":"Running the formatter on an empty .baml file; a formatter hook receiving empty editor buffers; corrupted or truncated source passed to the formatting pipeline.","solutions":["Ensure the source passed to the formatter is a non-empty BAML schema","Check for empty/truncated .baml files before running format","If the file should be valid, look for earlier parse errors (BAMLParser::parse would fail first) — an empty result usually means empty input","Add a pre-check: skip formatting when the source is blank"],"exampleFix":"// before\nlet formatted = format_schema(source, options)?;\n// after\nif source.trim().is_empty() {\n    return Ok(source.to_string());\n}\nlet formatted = format_schema(source, options)?;","handlingStrategy":"validation","validationCode":"if (source.trim().length === 0) { skip formatting; }","typeGuard":"function hasSchema(src) { return typeof src === 'string' && src.trim().length > 0; }","tryCatchPattern":"try { formatted = format_schema(src, opts); } catch (e) { if (e.message.includes('Expected a schema')) return src; throw e; }","preventionTips":["Skip formatting empty/blank files","Verify file contents before invoking the formatter","Check formatter hooks handle empty editor buffers"],"tags":["parser","formatter","empty-input","baml"],"backgroundTag":"empty-required-field","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}