BoundaryML/baml · error

interface frame starts with Self

Error message

interface frame starts with Self

What it means

While building packages, the compiler fetches an interface's frame parameters via `lower::interface_frame` and `.expect`s that the first parameter is `Self`. The panic means `interface_frame` returned an empty parameter list (or a list not starting with Self), so the interface lacks its implicit Self parameter.

Source

Thrown at baml_language/crates/baml_compiler2_emit/src/lib.rs:800

            let iface_tn = spelling.wire(&qualify_def(
                db,
                Definition::Interface(iface_loc),
                &iface_data.name,
            ));
            if !iface_data.fields.is_empty() {
                iface_field_decls
                    .entry(iface_tn.clone())
                    .or_insert_with(|| iface_data.fields.iter().map(|f| f.name.clone()).collect());
            }
            if !iface_data.associated_types.is_empty() {
                iface_assoc_decls
                    .entry(iface_tn.clone())
                    .or_insert_with(|| {
                        let frame_params =
                            baml_compiler2_hir_ty::lower::interface_frame(db, iface_loc);
                        let self_param = frame_params
                            .first()
                            .expect("interface frame starts with Self")
                            .clone();
                        (
                            self_param,
                            baml_compiler2_hir_ty::lower::interface_declared_params(db, iface_loc),
                            iface_data
                                .associated_types
                                .iter()
                                .map(|assoc| {
                                    (
                                        assoc.name.clone(),
                                        baml_compiler2_hir_ty::interfaces::
                                            interface_associated_type_default(
                                                db,
                                                iface_loc,
                                                assoc.name.clone(),
                                            )
                                            .map(|(ty, _decl_site_diags)| ty),
                                    )

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Fix the lowering pass so `interface_frame` always yields Self as the first parameter
  2. Verify `iface_loc` refers to the correct interface declaration (not a stale or wrong node)
  3. Clear incremental/cached HIR data and rebuild
  4. Add a defensive error path reporting which interface lacks Self instead of panicking
Defensive patterns

Strategy: validation

Validate before calling

let frame_params = lower::interface_frame(db, iface_loc);
if frame_params.first().map(|p| p.is_self()) != Some(true) {
    return Err(CompilerBug::InterfaceMissingSelf(iface_tn.clone()));
}

Type guard

fn frame_starts_with_self(params: &[Param]) -> bool {
    params.first().map(|p| p.is_self()).unwrap_or(false)
}

Try / catch

std::panic::catch_unwind(|| build_packages(db))
    .unwrap_or_else(|_| report_compiler_bug("interface frame missing Self"));

Prevention

When it happens

Trigger: Calling `build_packages` on an interface whose HIR frame has no leading Self parameter — e.g., the interface was built by a lowering pass that dropped the Self parameter, or the lookup `iface_loc` points at the wrong declaration node.

Common situations: Regressions in the HIR lowering for interfaces; malformed or hand-edited intermediate representations; resolving an interface location from a stale/cached index.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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