BoundaryML/baml · error

type `{ty}` can't be passed through auto-CLI; deliver it via

Error message

type `{ty}` can't be passed through auto-CLI; deliver it via `--json-args '{{ "<param>": ... }}' (or `--json-args @file` / `--json-args -` for stdin)

What it means

Auto-CLI only supports passing primitive-typed parameters as raw string flags. Types that can't survive shell quoting or aren't valid CLI parameter types (media, lists, objects, function/void/future, etc.) hit this catchall bail instead of being silently String-coerced. The error directs you to the JSON delivery path.

Source

Thrown at baml_language/crates/baml_exec/src/auto_cli.rs:100

            }
        }

        RuntimeTy::Enum(type_name, _) => Ok(BexExternalValue::Variant {
            enum_name: type_name.display_name().to_string(),
            variant_name: raw.to_string(),
        }),

        // Per BEP-027 §"Open questions" #5: anything auto-CLI can't
        // faithfully represent must be delivered via `--json-args`.
        // Structured types (class/list/map/union) are the obvious case;
        // media, literals, type aliases, opaque types, and the engine-
        // internal types (function/void/future) fall in the same
        // bucket — they either can't survive shell quoting or aren't
        // valid CLI parameter types. The previous catchall silently
        // String-coerced everything that fell through; that hides
        // genuine "this param can't be passed this way" errors behind a
        // confusing downstream type mismatch.
        _ => anyhow::bail!(
            "type `{ty}` can't be passed through auto-CLI; \
             deliver it via `--json-args '{{ \"<param>\": ... }}'` \
             (or `--json-args @file` / `--json-args -` for stdin)"
        ),
    }
}

#[cfg(test)]
mod tests {
    use baml_type::{MediaKind, TyAttr, TypeName};

    use super::*;

    fn ty_string() -> RuntimeTy {
        RuntimeTy::String {
            attr: TyAttr::default(),
        }
    }

View on GitHub (pinned to bd85ce9dee)

Solutions

  1. Deliver the parameter via `--json-args '{"<param>": ...}'`.
  2. Read the payload from a file with `--json-args @file`, or from stdin with `--json-args -`.
  3. If the value should be a simple flag, change the parameter's declared type to a primitive (string/int/float/bool).

Example fix

// before
baml run classify -- --image ./cat.png

// after
baml run classify -- --json-args '{"image": "./cat.png"}'
Defensive patterns

Strategy: validation

Validate before calling

// before invoking, check the param type in the signature help
if !matches!(ty, String | Int | Float | Bool) {
    args.json.insert(name.to_string(), json_value);
}

Try / catch

match result {
    Err(e) if e.to_string().contains("can't be passed through auto-CLI") => {
        eprintln!("move this parameter into --json-args");
    }
    other => other,
}

Prevention

When it happens

Trigger: Supplying a positional/flag value for a parameter whose runtime type falls into the unsupported bucket in `parse_cli_value` (non-primitive, non-nullable-union types like media, maps, lists of media, function/void/future).

Common situations: Trying to pass an image or structured object as a CLI flag, or calling an entry point whose signature includes media or complex types without using `--json-args`.

Understand the failure class

Background: "Unknown argument", "Invalid value", and "must be one of": invalid CLI argument errors explained — this error's family across 35 libraries.

Related errors


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