{"record":{"id":"b80ba4217a191c10","repo":"BoundaryML/baml","slug":"attempting-to-finish-a-call-without-first-starting-one","errorCode":null,"errorMessage":"Attempting to finish a call {:#?} without first starting one. Current context {:#?}","messagePattern":"Attempting to finish a call (.+?) without first starting one\\. Current context (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"engine/baml-runtime/src/tracing/mod.rs","lineNumber":499,"sourceCode":"            function_type,\n            is_stream,\n        );\n        BAML_TRACER.lock().unwrap().put(Arc::new(trace_event));\n\n        call\n    }\n\n    #[cfg(target_arch = \"wasm32\")]\n    pub(crate) async fn finish_call(\n        &self,\n        call: TracingCall,\n        ctx: &RuntimeContextManager,\n        response: Option<BamlValue>,\n    ) -> Result<uuid::Uuid> {\n        let guard = self.trace_stats.guard();\n\n        let Some((call_id, event_chain, tags)) = ctx.exit() else {\n            anyhow::bail!(\n                \"Attempting to finish a call {:#?} without first starting one. Current context {:#?}\",\n                call,\n                ctx\n            );\n        };\n\n        if call.call_id != call_id {\n            anyhow::bail!(\"Call ID mismatch: {} != {}\", call.call_id, call_id);\n        }\n\n        if let Some(tracer) = &self.tracer {\n            tracer\n                .submit(response.to_log_schema(&self.options, event_chain, tags, call))\n                .await?;\n            guard.done();\n            Ok(call_id)\n        } else {\n            guard.done();","sourceCodeStart":481,"sourceCodeEnd":517,"githubUrl":"https://github.com/BoundaryML/baml/blob/bd85ce9dee1463ff04d27efd20531013a4ff46c1/engine/baml-runtime/src/tracing/mod.rs#L481-L517","documentation":"In `finish_call` (tracing/mod.rs:499), `ctx.exit()` returned None, meaning no call was ever started in the current runtime context. BAML requires a matching start_call/finish_call pair per context; finishing without starting is an internal invariant violation, and the message dumps the call and context for debugging.","triggerScenarios":"Calling `finish_call` on a `RuntimeContextManager` whose stack has no active (call_id, event_chain, tags) entry — e.g. the start call never ran, ran in a different context, or the context was already exited.","commonSituations":"Custom integrations (language bindings, async runtimes) that call finish without start after an early error path; context clones/moves across threads so the started call is not visible; double-finishing the same call.","solutions":["Ensure every `finish_call` is paired with a successful `start_call` on the same RuntimeContextManager.","Check for early-return/error paths that skip start_call but still reach finish_call; guard them.","Verify the context manager instance is shared (not re-created) between the start and finish of the call.","Ensure finish_call is not invoked twice for the same call — the first exit() consumes the stack entry."],"exampleFix":"// before\nmanager.finish_call(call, &ctx, Some(response));\n// after: start first, finish exactly once\nmanager.start_call(&ctx, ...);\nmanager.finish_call(call, &ctx, Some(response));","handlingStrategy":"validation","validationCode":"// ensure a call is active before finishing\nif !ctx_has_active_call(&ctx) {\n    tracing::warn!(\"no active BAML call to finish; skipping\");\n    return;\n}","typeGuard":null,"tryCatchPattern":"if let Err(e) = runtime.finish_call(call, &ctx, response) {\n    if e.to_string().contains(\"without first starting one\") {\n        log::debug!(\"unpaired finish_call ignored: {e}\");\n    } else {\n        return Err(e);\n    }\n}","preventionTips":["Always pair start_call/finish_call in the same scope (use a guard struct with Drop).","Never create a new context manager between start and finish.","Finish each call exactly once; track with a flag.","Cover error paths in integration tests so start always precedes finish."],"tags":["tracing","state","invariant"],"backgroundTag":"invalid-state-transition","analyzedSha":"bd85ce9dee1463ff04d27efd20531013a4ff46c1","analyzedAt":"2026-09-12T03:38:25.718Z","contentChangedAt":"2026-09-12T03:38:25.718Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}