BoundaryML/baml · error · napi::Error

Invalid span args

Error message

Invalid span args

What it means

Span::new rejects span arguments that deserialize successfully but are not a JSON object (map). BAML requires call args to be a key/value map so they can be bound to function parameters; anything else yields 'Invalid span args' via invalid_argument_error.

Solutions

  1. Pass args as a plain object keyed by parameter names
  2. Check for undefined/null being passed as args
  3. Validate typeof args === 'object' && !Array.isArray(args) before the call
  4. Wrap the startSpan call in try/catch and log the offending args

Example fix

// before
const span = ctx.startSpan('MyFunc', [myValue], ctxManager, envVars);
// after
const span = ctx.startSpan('MyFunc', { myParam: myValue }, ctxManager, envVars);
Defensive patterns

Strategy: validation

Validate before calling

function toSpanArgs(args) {
  if (typeof args !== 'object' || args === null || Array.isArray(args)) throw new Error('span args must be an object keyed by parameter names');
  return args;
}

Type guard

const isValidSpanArgs = (args: unknown): args is Record<string, unknown> =>
  typeof args === 'object' && args !== null && !Array.isArray(args);

Try / catch

try {
  const span = ctx.startSpan(fnName, args, ctxManager, envVars);
  // ... run work, finish span
} catch (e) {
  if (String(e).includes('Invalid span args')) console.error('Bad span args:', args);
  throw e;
}

Prevention

When it happens

Trigger: Calling Span.new with args as an array, string, number, or null instead of an object — e.g. passing a single positional value rather than a parameter-name map.

Common situations: Passing the raw function argument instead of an args object, JSON output from another tool that wraps args in a list, or JS code passing undefined.

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

Appendix: source

Thrown at engine/language_client_typescript/src/types/span.rs:33

#[napi]
impl BamlSpan {
    #[napi(ts_return_type = "BamlSpan")]
    pub fn new(
        runtime: &BamlRuntime,
        function_name: String,
        args: serde_json::Value,
        ctx: &RuntimeContextManager,
        env_vars: serde_json::Value,
    ) -> napi::Result<Self> {
        let args: BamlValue = serde_json::from_value(args)
            .map_err(|e| napi::Error::new(napi::Status::GenericFailure, format!("{e:?}")))?;
        let Some(args_map) = args.as_map() else {
            return Err(invalid_argument_error("Invalid span args"));
        };

        let env_vars: HashMap<String, String> = serde_json::from_value(env_vars)
            .map_err(|e| napi::Error::new(napi::Status::GenericFailure, format!("{e:?}")))?;

        let call = runtime
            .inner
            .start_call(&function_name, args_map, &ctx.inner, &env_vars);
        log::trace!("Starting call: {call:#?} for {function_name:?}\n");
        Ok(Self {
            inner: call.into(),
            rt: runtime.inner.clone(),
        })
    }

    // mthod to finish
    #[napi]
    pub fn finish(
        &mut self,
        result: serde_json::Value,
        ctx: &RuntimeContextManager,
        env_vars: serde_json::Value,

View on GitHub (pinned to bd85ce9dee)