{"record":{"id":"15f34b3e9c1ddc80","repo":"BoundaryML/baml","slug":"invalid-span-args","errorCode":null,"errorMessage":"Invalid span args","messagePattern":"Invalid span args","errorType":"exception","errorClass":"napi::Error","httpStatus":null,"severity":"error","filePath":"engine/language_client_typescript/src/types/span.rs","lineNumber":33,"sourceCode":"\n#[napi]\nimpl BamlSpan {\n    #[napi(ts_return_type = \"BamlSpan\")]\n    pub fn new(\n        runtime: &BamlRuntime,\n        function_name: String,\n        args: serde_json::Value,\n        ctx: &RuntimeContextManager,\n        env_vars: serde_json::Value,\n    ) -> napi::Result<Self> {\n        let args: BamlValue = serde_json::from_value(args)\n            .map_err(|e| napi::Error::new(napi::Status::GenericFailure, format!(\"{e:?}\")))?;\n        let Some(args_map) = args.as_map() else {\n            return Err(invalid_argument_error(\"Invalid span args\"));\n        };\n\n        let env_vars: HashMap<String, String> = serde_json::from_value(env_vars)\n            .map_err(|e| napi::Error::new(napi::Status::GenericFailure, format!(\"{e:?}\")))?;\n\n        let call = runtime\n            .inner\n            .start_call(&function_name, args_map, &ctx.inner, &env_vars);\n        log::trace!(\"Starting call: {call:#?} for {function_name:?}\\n\");\n        Ok(Self {\n            inner: call.into(),\n            rt: runtime.inner.clone(),\n        })\n    }\n\n    // mthod to finish\n    #[napi]\n    pub fn finish(\n        &mut self,\n        result: serde_json::Value,\n        ctx: &RuntimeContextManager,\n        env_vars: serde_json::Value,","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/language_client_typescript/src/types/span.rs#L15-L51","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nconst span = ctx.startSpan('MyFunc', [myValue], ctxManager, envVars);\n// after\nconst span = ctx.startSpan('MyFunc', { myParam: myValue }, ctxManager, envVars);","handlingStrategy":"validation","validationCode":"function toSpanArgs(args) {\n  if (typeof args !== 'object' || args === null || Array.isArray(args)) throw new Error('span args must be an object keyed by parameter names');\n  return args;\n}","typeGuard":"const isValidSpanArgs = (args: unknown): args is Record<string, unknown> =>\n  typeof args === 'object' && args !== null && !Array.isArray(args);","tryCatchPattern":"try {\n  const span = ctx.startSpan(fnName, args, ctxManager, envVars);\n  // ... run work, finish span\n} catch (e) {\n  if (String(e).includes('Invalid span args')) console.error('Bad span args:', args);\n  throw e;\n}","preventionTips":["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"],"tags":["validation","arguments","span","typescript"],"backgroundTag":"invalid-argument-value","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}