Skip to main content

Traces not appearing in the dashboard

Symptom: You initialized the SDK and made LLM calls, but the dashboard shows no data after 15–30 seconds.
Verify the API key you passed to init() starts with zsp_ and matches the one shown in Settings → API Keys for your project. A typo or a key from a different project will cause all events to be silently dropped (the SDK logs a warning, but does not throw).Enable debug: true to see SDK activity:
zespan.init({
  apiKey: process.env.ZESPAN_API_KEY!,
  debug: true, // logs flush success/failure to console
});
The SDK batches events and flushes them every 2 seconds by default. If your script or Lambda handler exits before the flush fires, events are lost. Call flush() explicitly before the process ends:
await zespan.getClient().flush();
See the Serverless guide for environment-specific patterns.
If you self-host Zespan, make sure you set baseURL to your API server’s address. The default is https://api.zespan.com.
zespan.init({
  apiKey: "zsp_...",
  baseURL: "https://api.yourdomain.com",
});
The SDK sends events to https://api.zespan.com over HTTPS (port 443). If your environment blocks outbound traffic, allowlist this endpoint. Use debug: true to see if flush requests are failing with network errors.
zespan.init() must be called before any wrapped LLM client is created.
// ✓ Correct — init before wrap
zespan.init({ apiKey: "zsp_..." });
const openai = zespan.wrapOpenAI(new OpenAI());

// ✗ Wrong — wrap before init
const openai = zespan.wrapOpenAI(new OpenAI());
zespan.init({ apiKey: "zsp_..." });

Cost showing $0.00 for all events

Symptom: Traces appear in the dashboard but the cost_usd column is always zero.
The SDK computes cost from a built-in pricing table keyed on the exact model string. If you use a model ID the SDK doesn’t recognise, cost_usd is set to 0 rather than throwing an error.Check your model strings against the supported models reference. Common mismatches:
You sendSDK expects
gpt4ogpt-4o
claude-3-5-sonnetclaude-3-5-sonnet-20241022
gemini-progemini-1.5-pro
If you use a model not in the table, open an issue on GitHub — we add new models with each release.
If input_tokens or output_tokens are 0, cost will also be 0. This can happen if the provider response doesn’t include usage data — for example, streaming calls where you don’t consume the full stream before closing it.For streaming calls, make sure you iterate the full response before the function returns:
const stream = await openai.chat.completions.create({ stream: true, ... });
for await (const chunk of stream) {
  // consume every chunk
}
// Usage data is in the final chunk — the SDK captures it automatically

Parent-child spans not linking (broken trace tree)

Symptom: Multi-step agent workflows show as separate disconnected traces instead of a nested tree.
The SDK propagates trace context automatically through async calls. If you break the async chain — for example, by using setTimeout, setImmediate, or a non-async callback — context is lost.Always use await for async operations inside withLumiqtraceContext or withAgent:
// ✓ Context propagates correctly
await withAgent({ name: "MyAgent" }, async (agent) => {
  await agent.traceTool("fetch-data", {}, () => fetchData());
});

// ✗ Context is lost inside setTimeout
await withAgent({ name: "MyAgent" }, async (agent) => {
  setTimeout(() => fetchData(), 0); // no await — context is dropped
});
If you call wrapped LLM clients outside a withLumiqtraceContext block, each call gets its own isolated trace context and cannot link to siblings.Wrap your entire request handler:
export async function POST(req: Request) {
  const { userId, sessionId } = await getSession(req);

  return withLumiqtraceContext({ userId, sessionId }, async () => {
    const summary = await summarize(text);
    const response = await generate(summary);
    return Response.json({ response });
  });
}
If you don’t await withAgent(...), the agent span may close before inner spans complete, breaking the parent-child link.
// ✓ Correct
await withAgent({ name: "MyAgent" }, async (agent) => { ... });

// ✗ Wrong — span closes immediately
withAgent({ name: "MyAgent" }, async (agent) => { ... });

Events missing in serverless (Lambda / Vercel / Cloud Run)

See the complete Serverless deployment guide for environment-specific patterns. Quick fix: call flush() before your handler returns.
# Python Lambda
def handler(event, context):
    result = call_llm(event["prompt"])
    zespan.flush()  # must be last line before return
    return {"body": result}
// TypeScript Lambda / Vercel
export default async function handler(req, res) {
  const result = await callLLM(req.body.prompt);
  await zespan.getClient().flush(); // must await before responding
  res.json({ result });
}

401 Unauthorized from the ingest endpoint

Cause: One of the following:
  1. The API key was revoked or rotated and the old key is still in use
  2. The x-api-key header is missing from the request
  3. The key belongs to a different project
Go to Settings → API Keys, check that the key prefix matches the one your application is using, and rotate if necessary.

Rate limit 429 with “Monthly quota exceeded”

This is not a per-minute rate limit — it means your organization has exhausted its monthly event quota. Retrying later in the same month will not succeed. Options:
  • Upgrade your plan from Settings → Billing
  • Reduce your SDK sampleRate to send fewer events: zespan.init({ sampleRate: 0.5 })
  • Wait for your quota to reset at the start of next month

Prompt text not showing in trace detail

Cause: Prompt storage is on by default but may have been disabled. Verify storePrompts is not set to false in your init() call — PII redaction is applied to all stored text before transmission:
zespan.init({
  apiKey: "zsp_...",
  storePrompts: true, // default — set false to disable
});
Review your data retention policy before enabling this. Once stored, prompt text is subject to your plan’s retention window.

Python SDK not capturing async OpenAI calls

zespan.patch_openai() patches both sync and async clients. If async calls are still not traced, verify:
  1. patch_openai() is called before any openai module is imported in your actual call path
  2. You are using openai.AsyncOpenAI() (not a pre-initialized client from before the patch)
import zespan
zespan.init(api_key="zsp_...")
zespan.patch_openai()

# Create client AFTER patching
import openai
client = openai.AsyncOpenAI()  # ✓ this is patched

Still stuck?

Enable debug: true in your SDK init and share the console output. Open an issue on GitHub or email support@zespan.com.