BoundaryML/baml · error

two targets share subcommand name `{}` (`{}` and `{}`). Subc

Error message

two targets share subcommand name `{}` (`{}` and `{}`). Subcommand names come from the last `.`-segment of the function name; rename one of them so the binary's subcommands stay unambiguous.

What it means

resolve_targets checks that every resolved pack target has a unique subcommand name, derived from the last `.`-segment of the function's qualified name (e.g. `user.Foo` and `admin.Foo` both yield `Foo`). If two `-f` targets collide, the packed subcommand binary would have ambiguous subcommands, so the CLI bails naming both full function names.

Source

Thrown at baml_language/crates/baml_cli/src/pack_command.rs:399

    /// layer per the spec).
    fn resolve_targets(
        &self,
        engine: &BexEngine,
    ) -> Result<(baml_exec::PackMode, Vec<ResolvedPackTarget>)> {
        if let Some(target) = self.target.as_deref() {
            let resolved = resolve_one(engine, target)?;
            return Ok((baml_exec::PackMode::Single, vec![resolved]));
        }

        // Subcommand mode. Resolve each `-f` and reject duplicate subcommand names.
        let mut resolved: Vec<ResolvedPackTarget> = Vec::with_capacity(self.functions.len());
        for func in &self.functions {
            resolved.push(resolve_one(engine, func)?);
        }
        let mut seen: HashMap<&str, &str> = HashMap::new();
        for r in &resolved {
            if let Some(prev) = seen.insert(r.subcommand_name.as_str(), r.display_name.as_str()) {
                anyhow::bail!(
                    "two targets share subcommand name `{}` (`{}` and `{}`). \
                     Subcommand names come from the last `.`-segment of the function name; \
                     rename one of them so the binary's subcommands stay unambiguous.",
                    r.subcommand_name,
                    prev,
                    r.display_name,
                );
            }
        }
        Ok((baml_exec::PackMode::Subcommand, resolved))
    }

    /// Pick the default output basename.
    ///
    /// - `--file <PATH>` single-file mode: file stem (e.g. `foo.baml` →
    ///   `foo`). `baml.toml` isn't consulted — single-file packs are
    ///   intentionally hermetic.
    /// - Project mode: `[package].name` from `<from>/baml.toml` when a

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Rename one of the colliding functions (or move it so its last `.`-segment differs) in the `.baml` source.
  2. Pack fewer functions — drop one of the colliding `-f` targets.
  3. Pack each colliding function as a separate single-entry binary using the positional target instead.

Example fix

// before
baml pack -f user.Greet -f admin.Greet

// after (rename one function in source)
baml pack -f user.Greet -f admin.AdminGreet
Defensive patterns

Strategy: validation

Validate before calling

# ensure unique last segments among -f targets
NAMES="user.Greet admin.Greet"
dups=$(echo "$NAMES" | tr ' ' '\n' | awk -F. '{print $NF}' | sort | uniq -d)
[ -n "$dups" ] && { echo "colliding subcommand names: $dups" >&2; exit 2; }

Prevention

When it happens

Trigger: Running `baml pack -f ns1.MyFunc -f ns2.MyFunc` (or two unqualified names resolving to functions in different modules) where both functions share the same final segment.

Common situations: Packing same-named functions defined in different BAML modules/namespaces; renaming a module without noticing a name collision; auto-generating `-f` lists from scripts that collect qualified names.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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