API URL conflicts in self-hosted deployments
API URL conflicts in self-hosted deployments
Issue: Streaming logs fail with initialization or forbidden errors when
apiUrl, appUrl, or BRAINTRUST_API_URL point to conflicting environments.Cause: The SDK sends logging requests to the API/data plane URL. If apiUrl is set, it takes precedence over appUrl.Fix: For Braintrust-hosted projects, remove custom URL settings unless you use a custom frontend. For self-hosted or hybrid projects, set only apiUrl or BRAINTRUST_API_URL to the data plane endpoint.Evals fail from resource exhaustion or EMFILE errors
Evals fail from resource exhaustion or EMFILE errors
Issue: Evals fail, time out, produce incomplete results, or hit
EMFILE: too many open files.Cause: Eval() runs tasks with unlimited concurrency unless maxConcurrency is set. That can exhaust file descriptors, memory, database pools, or model-provider rate limits.Fix: Set maxConcurrency to a small value such as 10, then tune up or down based on the workload.Eval process hangs after completion
Eval process hangs after completion
Issue:
braintrust eval prints results successfully, but the Node.js process does not exit.Cause: Open handles in your eval process can keep the Node.js event loop alive. Common sources include database pools, Redis clients, WebSockets, and HTTP keep-alive agents.Fix: Run the eval with the Node inspector to identify active handles, then explicitly close external resources after the eval finishes.Traces are missing, empty, or stuck in progress
Traces are missing, empty, or stuck in progress
Issue: Traces don’t appear, show empty fields, never leave “in progress”, or don’t include final values.Cause: A process can exit before logs flush, or an exception can bypass
end() on a manually-created span.Fix: Prefer traced() — it ends the span for you, even when the wrapped function throws. If you use startSpan() directly, call end() in finally. Either way, call flush() before a short-lived process exits.Trace continuity breaks after restarts
Trace continuity breaks after restarts
Issue: Follow-up turns in an existing conversation stop appearing under the original trace after a server restart or pod replacement.Cause: Exported span context from
span.export() was kept only in memory. After restart, the SDK cannot continue the previous trace.Fix: Persist the exported span context. On the next request, wrap the work in withParent(), or pass the stored value as parent to traced() or startSpan().Prompt version IDs do not match the UI
Prompt version IDs do not match the UI
Issue:
prompt.version returns a large decimal string, while the Braintrust UI shows a short hexadecimal version ID.Cause: The SDK returns the raw transaction ID. The UI displays a prettified, reversible version of the same ID.Fix: Convert SDK values to the UI form with prettifyXact(), or back with loadPrettyXact(). Both are exported from braintrust/util.Prompt shows None in experiment view
Prompt shows None in experiment view
Issue: The experiment view shows
Prompt: None, even though your task uses a prompt.Cause: On LLM spans, the UI detects prompts from prompt metadata. Hard-coded prompts or prompts sent without the Braintrust prompt workflow do not attach that metadata.Fix: Fetch the prompt with loadPrompt(), call prompt.build({ input }) to produce the messages and parameters, then send them through a wrapped client (wrapOpenAI, wrapAnthropic, etc.). The wrapper reads the metadata from build() and attaches it to the LLM span.GPT-5 prompts include unsupported temperature
GPT-5 prompts include unsupported temperature
Issue: A prompt configured for a GPT-5 model returns
temperature from prompt.build(), and passing those parameters to OpenAI fails.Cause: Braintrust prompts can store temperature regardless of the selected model, but GPT-5 models reject temperature on the OpenAI API.Fix: Strip temperature from the parameters before sending the request, as shown below.No traces sent from a deployment on Vercel
No traces sent from a deployment on Vercel
Issue: You see only some traces, or none at all, from a deployment on Vercel.Cause: Vercel freezes the function as soon as it returns a response, so events still in Braintrust’s buffer may never flush.Fix: Call
flush() in your application code after your AI calls. On Vercel, flush() sends buffered data even after the response has been returned.