> ## Documentation Index
> Fetch the complete documentation index at: https://docs.uselemma.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Common issues

> Troubleshoot missing traces and trace-quality issues: lost context, invisible tools, blank input/output, and unsupported shapes

This page is organized by **symptom**. Most issues are trace-shape problems: the data arrives, but it does not match the [trace contract](/reference/trace-contract). For a visual reference of malformed vs conformant traces, see [Good trace vs bad trace](/reference/good-vs-bad-traces).

<Note>
  When behavior is unclear, first enable [Debug mode](/tracing/troubleshooting/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.
</Note>

## 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.

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    import { Lemma } from "@uselemma/tracing";

    const lemma = new Lemma({
      apiKey: process.env.LEMMA_API_KEY,
      projectId: process.env.LEMMA_PROJECT_ID,
    });

    await lemma.trace({ name: "smoke-test", input: "hello" }, async () => "ok");
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import os

    from uselemma_tracing import Lemma

    lemma = Lemma(
        api_key=os.environ["LEMMA_API_KEY"],
        project_id=os.environ["LEMMA_PROJECT_ID"],
    )

    lemma.trace("smoke-test", lambda trace: "ok", input="hello")
    ```
  </Tab>
</Tabs>

* 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=true` 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.

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    const answer = await lemma.trace(
      { name: "support-agent", input: userMessage, threadId, userId },
      async (trace) => {
        const docs = await searchDocs(userMessage);
        trace.recordTool({ name: "search_docs", input: { query: userMessage }, output: docs });

        const response = await callModel(userMessage, docs);
        trace.recordGeneration({
          name: "answer",
          model: response.model,
          input: response.messages,
          output: response.text,
        });

        return response.text;
      },
    );
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    def run(trace):
        docs = search_docs(user_message)
        trace.record_tool(
            name="search_docs",
            input={"query": user_message},
            output=docs,
        )

        response = call_model(user_message, docs)
        trace.record_generation(
            name="answer",
            model=response.model,
            input=response.messages,
            output=response.text,
        )

        return response.text

    answer = lemma.trace(
        "support-agent",
        run,
        input=user_message,
        thread_id=thread_id,
        user_id=user_id,
    )
    ```
  </Tab>
</Tabs>

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.

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    const result = await lookupOrder(orderId);
    trace.recordTool({
      name: "lookup_order",
      input: { orderId },
      output: result,
    });
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    result = lookup_order(order_id)
    trace.record_tool(
        name="lookup_order",
        input={"order_id": order_id},
        output=result,
    )
    ```
  </Tab>
</Tabs>

For failures, record the error before re-raising:

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    try {
      return await chargeCard(payload);
    } catch (error) {
      trace.recordTool({ name: "charge_card", input: payload, error });
      throw error;
    }
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    try:
        return charge_card(payload)
    except Exception as error:
        trace.record_tool(name="charge_card", input=payload, error=error)
        raise
    ```
  </Tab>
</Tabs>

**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.

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    await lemma.trace({ name: "support-agent", input: userMessage }, async (trace) => {
      const answer = await runAgent(userMessage);
      trace.output(answer);
      return answer;
    });
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    def run(trace):
        answer = run_agent(user_message)
        trace.output(answer)
        return answer

    lemma.trace("support-agent", run, input=user_message)
    ```
  </Tab>
</Tabs>

**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(...)`.

## 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()`.

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    trace.recordGeneration({
      name: "draft-reply",
      model: "gpt-4o",
      input: messages,
      output: response.text,
    });
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    trace.record_generation(
        name="draft-reply",
        model="gpt-4o",
        input=messages,
        output=response.text,
    )
    ```
  </Tab>
</Tabs>

See [Generations](/tracing/instrumentation/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.

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    await lemma.trace({ name: "support-agent", input: userMessage }, async (trace) => {
      return runAgent(userMessage, trace);
    });
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    lemma.trace(
        "support-agent",
        lambda trace: run_agent(user_message, trace),
        input=user_message,
    )
    ```
  </Tab>
</Tabs>

**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.

<Tabs>
  <Tab title="TypeScript">
    ```typescript theme={null}
    const retrieve = trace.startSpan({ name: "retrieve-context", input: { query } });
    try {
      const docs = await searchDocs(query);
      retrieve.recordTool({ name: "search_docs", input: { query }, output: docs });
      retrieve.end({ output: { count: docs.length } });
      return docs;
    } catch (error) {
      retrieve.end({ error });
      throw error;
    }
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    retrieve = trace.start_span(name="retrieve-context", input={"query": query})
    try:
        docs = search_docs(query)
        tool = trace.start_tool(
            name="search_docs",
            input={"query": query},
            parent_id=retrieve.id,
        )
        tool.end(output=docs)
        retrieve.end(output={"count": len(docs)})
        return docs
    except Exception as error:
        retrieve.end(error=error)
        raise
    ```
  </Tab>
</Tabs>

```text theme={null}
support-agent
├─ retrieve-context
│  └─ search_docs
└─ answer
```

**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 flush or 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.
