Skip to main content
This page is organized by symptom. Most issues are trace-shape problems: the data arrives, but it does not match the trace contract. For the ideal happy path and bad → better → best examples, see Building high-quality traces.
When behavior is unclear, first enable Debug mode in the same runtime that serves traffic. It shows whether the SDK is running, which trace it tries to send, how many child spans were included, and whether the ingest request succeeds.

No traces in Lemma

Cause: credentials, project ID, base URL, or outbound network access is wrong. Fix: create one Lemma client with your API key and project ID, then send a tiny test trace.
  • Confirm LEMMA_API_KEY and LEMMA_PROJECT_ID come from the same project.
  • Confirm your runtime can reach https://api.uselemma.ai.
  • Pass baseUrl / base_url only when using a self-hosted or staging endpoint.
Debug with Debug mode: enable LEMMA_DEBUG=1 and run the smoke test again. If you do not see SDK logs, the traced code path is not running in that process. If you see an ingest failure, check the status code, credentials, project ID, and baseUrl.

Every span appears as a separate trace

Cause: child work is being recorded outside the lemma.trace() callback, so the SDK cannot attach it to the root trace. Fix: make lemma.trace() the boundary around the whole agent run, and record tools, generations, and spans inside that callback.
Across queues, workers, or separate services, start a new top-level trace and pass the same threadId / userId so turns remain connected. If one logical agent execution spans multiple processes, prefer recording the final trace in the coordinator that has the complete input, output, tools, and model calls. Debug with Debug mode: compare logs from the request handler and any background worker. If the child work runs after the lemma.trace() callback has returned, it will not attach to the root trace automatically. Move the recording into the callback, or pass trace/span IDs and use the detached record* helpers from the coordinator.

Tool calls are missing

Cause: provider instrumentation captures model calls but not your application tools, or the tool result is never recorded. Fix: call trace.recordTool() after each tool completes.
For failures, record the error before re-raising:
Debug with Debug mode: check the spanCount (span_count in Python) on the sending trace log. If the count does not increase after you add recordTool(...), the tool recording code path is not running or is running outside the trace.

Inputs or outputs are blank

Cause: the trace was created without input, and the callback did not return or set the final output. Fix: pass input to lemma.trace() and return the final answer. Use trace.output() only when the callback return value is not the user-visible output.
Debug with Debug mode: confirm the trace logs trace sent, then open that trace in Lemma. If root output is still blank, the callback likely returned undefined, streamed the answer elsewhere, or exited before setting trace.output(...).

Root input/output is null after a second delivery

Cause: the trace was delivered again with a sparse ingest() payload — for example a follow-up call that carries a late child span but omits root input/output. ingest() is not an incremental merge API, so omitted root fields do not preserve prior values, and analysis typically already ran once after the first complete delivery. Fix: send one complete trace when the execution finishes — root input/output, thread/user, and all child spans in a single ingest() call. Retries of that same complete payload are safe (already-stored span IDs are skipped). Across queues and workers, assemble the full tree in a coordinator and ingest once rather than streaming partial deliveries under one trace.id. Debug with Debug mode: check the sending trace log for each delivery. If a later send has a small spanCount (span_count in Python) and no root I/O, that sparse payload is overwriting the root fields — consolidate it into the single terminal send.

Model or content is missing

Cause: the LLM call is recorded as a generic span, so Lemma has no model, prompt, or completion to read as a generation. Fix: record model calls with trace.recordGeneration().
See Generations. Debug with Debug mode: check whether spanCount (span_count in Python) increases when the model call runs. If it does but the dashboard still lacks model/content metadata, switch that call site from generic span recording to recordGeneration() / record_generation() and include model, input, and output.

Agent name is blank

Cause: no stable name is attached to the trace, so traces cannot be grouped or filtered by workflow. Fix: set name on every lemma.trace() call.
Debug with Debug mode: check the name on trace started or sending trace. It should be the stable workflow name you expect, not a generated fallback.

Trace Nesting Is Flat

Cause: long-running subtasks are recorded as sibling observations when they should have their own parent span. Fix: use trace.startSpan() / trace.start_span() when a subtask has nested work. In TypeScript, record children from the span handle. In Python, pass the parent span handle’s id as parent_id when starting child work.
Debug with Debug mode: confirm spanCount (span_count in Python) includes both the parent span and the child tool, then inspect the trace in Lemma. If they appear as siblings, record the child from the parent span handle in TypeScript, or pass parent_id=retrieve.id when starting the child in Python, before ending the parent span.

Serverless traces are delayed or missing

Cause: the request exits before the SDK request finishes, or a background task records work after the trace callback has returned. Fix: await lemma.trace(...) inside the handler and keep trace recording inside the callback. The SDK sends the completed payload before lemma.trace() resolves. Debug with Debug mode: check whether the ingest log appears before the function returns. If it appears after the response is sent, or never appears, await the trace promise and avoid detached background recording unless you explicitly end the trace handle.

Traces render but there are no issues or incidents

Cause: the trace renders, but it is not in a shape Lemma recognizes for automated issue detection. Fix: match the contract: one root trace, input/output, typed generation children, typed tool children, error states, and thread/user context where available.
  • Use lemma.trace() for the root.
  • Use trace.recordGeneration() / trace.record_generation() for model calls.
  • Use trace.recordTool() / trace.record_tool() for tool calls.
  • Use trace.recordSpan() / trace.record_span() for completed app work or trace.startSpan() / trace.start_span() for live app work.
  • Pass threadId / thread_id and userId / user_id for multi-turn analysis.
Debug with Debug mode: confirm the SDK logs trace sent with the expected trace name and child spanCount (span_count in Python), then compare the dashboard trace against the contract.