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
- Pass args as a plain object keyed by parameter names
- Check for undefined/null being passed as args
- Validate typeof args === 'object' && !Array.isArray(args) before the call
- 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
- Always pass an object keyed by BAML function parameter names
- Reject null/undefined/array args before startSpan
- Centralize span creation in a helper that validates args once
- Unit-test span creation with representative args
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
- BamlValidationError
- {e:?}
- Missing argument ' ' for function
- missing parameter
- Missing required parameter
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)