BoundaryML/baml · error

interned member `{name}` cannot be another member's child

Error message

interned member `{name}` cannot be another member's child

What it means

A derive macro for BAML's interned type families rejects a plain (non-interned) member whose child is an interned member. This is structurally impossible to support because automatic conversion walkers cannot convert through a handle; only hand-written boundary conversions can. The macro fails at parse/derivation time before any code is generated.

Source

Thrown at baml_language/crates/baml_type_macros/src/parse.rs:329

        let resolved_members = members
            .iter()
            .enumerate()
            .map(|(i, m)| {
                let includes = m
                    .includes
                    .iter()
                    .map(&axis_index)
                    .collect::<syn::Result<Vec<_>>>()?;
                let child = match &m.child {
                    ChildRef::SelfRef => Child::Member(i),
                    ChildRef::Named(name) => {
                        let idx = member_index(name)?;
                        // A plain member cannot nest an interned member: the
                        // structural conversion walkers would have to convert
                        // through a handle, which only the hand-written
                        // boundary conversions can do.
                        if matches!(members[idx].child, ChildRef::Interned(_)) {
                            return Err(syn::Error::new(
                                name.span(),
                                format!(
                                    "interned member `{name}` cannot be another member's child"
                                ),
                            ));
                        }
                        Child::Member(idx)
                    }
                    ChildRef::Interned(handle) => {
                        if m.name == master_ident {
                            return Err(syn::Error::new(
                                m.name.span(),
                                "the master member cannot be interned: the master is the \
                                 plain tree every other member converts through",
                            ));
                        }
                        Child::Interned(Box::new(handle.clone()))
                    }

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Make the child member plain (remove its interning) so nesting stays in the walker-convertible plain tree.
  2. Convert the parent into an interned member too, so the nesting lives behind a handle processed by boundary conversions.
  3. Restructure so interned members only appear at the top level, not as children of other members.

Example fix

// before
member Plain {
  child: InternedMember,
}
// after
member Plain {
  child: PlainChild,
}
member PlainChild { /* plain fields */ }
Defensive patterns

Strategy: validation

Validate before calling

// at macro-input authoring time
assert!(!members.iter().any(|m| matches!(m.child, ChildRef::Interned(_))),
    "plain members must not nest interned members");

Type guard

fn is_plain_child(m: &Member) -> bool { !matches!(m.child, ChildRef::Interned(_)) }

Prevention

When it happens

Trigger: Declaring a derive input where `member_index(name)` resolves to a member whose `ChildRef` is `ChildRef::Interned(_)` — i.e. writing a plain member that nests another member marked as interned.

Common situations: Developers mixing plain and interned members in one type-family definition, assuming arbitrary nesting works; or refactoring a plain tree to add interning and marking the wrong level interned.

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/eff13888796f9ff1. Report an issue: GitHub.