Troubleshoot a failed integration
Start from the stable code, status, or result that your backend observed. Use this guide to collect safe evidence and choose a platform operation without logging credentials or sensitive inputs.
Start with the symptom
Authentication failures
Requests fail before a tenant is resolved.
Provider failures
A stored Provider test or model Turn cannot reach the model.
Streaming failures
A successful stream starts and its final result later rejects.
MCP failures
Connection validation, credentials, or Tool discovery fails.
Sandbox failures
File-operation execution lacks an attached Sandbox.
Task failures
A background run reaches a non-success terminal state.
Quota failures
A Turn is denied or a Task becomes blocked.
| Observed symptom | Diagnostic branch |
|---|---|
| HTTP 401 | Authentication failures |
provider_error or failed Provider test | Provider failures |
stream_error after output begins | Streaming failures |
MCP test failure or connection error | MCP failures |
SANDBOX_REQUIRED | Sandbox failures |
Task run failed or canceled | Task failures |
quota_exceeded or Task run blocked | Quota failures |
Authentication failures
| Evidence | Detail |
|---|---|
| Stable symptom/error or status | unauthorized with HTTP 401 |
| Safe diagnostic | Confirm that the backend sent one Authorization: Bearer value and record the response status and X-Request-Id; do not record the value. |
| Likely cause | The credential is missing, invalid, deleted, or an API-key record ID was sent instead of the one-time ba_… secret. |
| Next action | First obtain another valid tenant API key for the SDK, or an authenticated admin-session JWT for REST; the failed credential cannot authorize its own recovery. Then inspect apiKeys.list(), create and securely deploy a replacement with apiKeys.create(), or use the REST list API keys and create API key operations. |
Provider failures
| Evidence | Detail |
|---|---|
| Stable symptom/error or status | A Turn reports provider_error, or a stored Provider test returns { ok: false, error: { code: "provider_error" } }. |
| Safe diagnostic | Read the Agent with agents.get() or REST get Agent. Record its providerId, model, and the test result code; with a response-capturing transport, also record X-Request-Id. Redact keys and upstream error text. |
| Likely cause | When providerId is null, the Agent uses the platform OpenRouter key and the selected model may be unavailable or rejected. Otherwise, the stored Provider's key, base URL, upstream account, type, or the Agent's model may be invalid. |
| Next action | For providerId: null, select a valid model or attach a stored Provider with agents.update() or REST update Agent; there is no stored Provider resource to test. For a stored Provider, run providers.testStored() or REST test stored Provider. Change only its name or base URL with providers.update() or REST update Provider. Replacing a key or Provider type requires a new Provider and the Pin-safe migration below. |
When a key or Provider type changes, migrate the references as well as the current Agent:
- Validate the new configuration with
providers.test()or REST test Provider config, then save it withproviders.create()or REST create Provider. - Enumerate all current Agents with
agents.list()or REST list Agents. A shared Provider may appear only in history, so page every Agent's Versions withagents.listVersions()or REST list Agent Versions, and inspect each Version'sproviderId; checking only each Agent's currentproviderIdis insufficient. - Find the Version resolved by each affected execution. For each Task with a
non-null
activeRunId, read that run withtasks.getRun()or REST get Task run. For a complete historical audit, pagetasks.listRuns()or REST list Task runs to cursor exhaustion. Each run exposesagentVersion. For every Agent, also pagesessions.list()or REST list Sessions to cursor exhaustion; pinned Sessions expose their configuredagentVersion. Inspect each referenced immutable Version withagents.getVersion()or REST get Agent Version. - Point every affected current Agent at the replacement with
agents.update()or REST update Agent. This creates a new Version; it does not rewrite historical Versions. - Page affected definitions to cursor exhaustion with
tasks.list()or REST list Tasks. Usetasks.update()or REST update Task to setagentVersionto the replacement Version, or tonullto follow latest. - A queued or running Task run keeps the Version resolved when it was
enqueued, even after its Task Pin changes. Let old-Version runs reach a
terminal state, or request cancellation with
tasks.cancelRun()or REST cancel Task run, and verify the terminal result with the Task-run reads above. - A Session Pin cannot be changed. Start a replacement Session with the new
Version through
client.chat()or REST create a Session turn. Unpinned Sessions follow latest and do not need replacement.
Keep the old Provider while any historical Version Pin must remain usable.
providers.delete() and REST
delete Provider check current
Agent references, not historical Versions. Deletion makes future Provider
resolution fail for every remaining Task Pin, Session Pin, queued Task run, or
explicit stateless Pin whose historical Version contains that ID. It does not
revoke credentials already resolved and decrypted for an admitted Turn, so
that Turn may finish. A Task run still before Provider resolution can become
failed; its untyped error is not a stable code and must not be matched for
an internal error name. A synchronous request instead exposes the public
not_found HTTP 404. Preserve the
drain-or-cancel procedure above and observe every old-Version run's terminal
state before deleting the Provider.
Streaming failures
| Evidence | Detail |
|---|---|
| Stable symptom/error or status | Completion or object output begins, then the final result rejects with SDK stream_error. |
| Safe diagnostic | Record the generation kind, whether any deltas arrived, the SDK code/status, and the original response request ID when your transport captures it. Do not log streamed content. |
| Likely cause | The transport or in-loop execution failed after HTTP headers were committed, so the response status could no longer change. |
| Next action | Always await result.text or result.object, handle the rejection, and retry only if your operation is safe to repeat. See the REST generate operation and streaming protocol. |
MCP failures
| Evidence | Detail |
|---|---|
| Stable symptom/error or status | An MCP test returns MCP_CONNECTION_AUTHENTICATION_FAILED, MCP_CONNECTION_UNREACHABLE, or MCP_CONNECTION_DISCOVERY_FAILED, or the connection status is needs_auth or error. |
| Safe diagnostic | Record the MCP Connection ID, status, lastAuthErrorCode, and test code. With raw REST or a response-capturing transport, also record X-Request-Id. Do not log bearer tokens, OAuth secrets, or discovered Tool inputs/results. |
| Likely cause | Credentials were rejected, the remote Streamable HTTP endpoint was unreachable, or Tool discovery failed. |
| Next action | Run mcpConnections.test() or REST test MCP connection. For none, bearer, or client-credentials authentication, replace the URL or credentials with reconnect() or REST reconnect MCP connection. For authorization-code OAuth, reconnect changed configuration when needed, then use the Tenant-admin session connect() or REST connect MCP connection flow and complete the returned browser authorization; an API-key SDK client receives HTTP 403 from connect. |
Sandbox failures
| Evidence | Detail |
|---|---|
| Stable symptom/error or status | SANDBOX_REQUIRED with HTTP 409 |
| Safe diagnostic | Record the Agent ID, Sandbox ID if present, selected Tool group names, status, and request ID. Do not collect workspace contents. |
| Likely cause | The Agent selected file_operation_sandbox without a valid tenant-owned Sandbox attachment. |
| Next action | Read the Agent with agents.get(), then attach an existing Sandbox through agents.update(). See get Agent and update Agent. |
Normal Sandbox contention waits for durable admission; it does not return a busy error.
Task failures
| Evidence | Detail |
|---|---|
| Stable symptom/error or status | A Task run reaches failed or canceled; queued and running are not terminal. |
| Safe diagnostic | Record the Task ID, run ID, status, and timestamps. A run's error can contain an arbitrary Error.message; treat it as untrusted and potentially sensitive, and redact it before logging or sharing. Read transcript structure, but redact message parts before sharing diagnostics. |
| Likely cause | Execution failed, an interruption was finalized without replay, the worker deadline elapsed, or cooperative cancellation won the race. |
| Next action | Inspect tasks.getRun() and tasks.runMessages(). REST equivalents are get Task run and list Task run messages. Submit a new run with a new stable key only after deciding the Task's effects are safe to repeat. |
Quota failures
| Evidence | Detail |
|---|---|
| Stable symptom/error or status | A synchronous Turn returns quota_exceeded with HTTP 429, or a Task run reaches terminal blocked. |
| Safe diagnostic | Record the status/code, Task and run IDs when applicable, usage totals, quota ceilings, reset day, and request ID. Do not include prompts or credentials. |
| Likely cause | Settled request or combined input/output token usage is already above the configured monthly ceiling. |
| Next action | Query usage.get(), read tenant.get(), and adjust policy through tenant.patch() if appropriate. REST equivalents are get usage, get tenant settings, and update tenant settings. |
Collect safe diagnostics
The SDK exposes code and optional HTTP status on BlazingAgentsError.
Resource IDs and the REST response's X-Request-Id are safe correlation fields
when they do not encode your own sensitive metadata.
import { BlazingAgentsError } from "@blazing-agents/sdk";
try {
await client.tasks.get(taskId);
} catch (error) {
if (!BlazingAgentsError.isInstance(error)) throw error;
console.error({
code: error.code,
resourceId: taskId,
status: error.status,
});
}Never log API keys, Provider credentials, MCP credentials, raw prompts,
message parts, Tool inputs/results, or Sandbox file contents. Redact upstream
messages before sharing them because the SDK's message is human-readable
context, not a stable diagnostic code.
The example reads the definition with tasks.get();
the equivalent REST operation is get Task.
Related capabilities
- Security and credentials
- Models and Providers
- Generation and streaming
- MCP connections
- Sandboxes
- Tasks and schedules
- Usage and quotas
- Limits and reliability
SDK and REST reference
Use the canonical error contract for the wire envelope, SDK codes, statuses, and stream boundaries. The branch tables link the exact TypeScript SDK and REST operations used for each diagnostic and recovery action; the REST authentication contract explains the shared Bearer boundary.