---
title: "SDK troubleshooting: symptoms, causes, and fixes"
description: "Match Duale AI SDK error symptoms to causes and fixes for model() exceptions, authentication, libraries, documents, and Tool Host issues."
lang: en
status: public-preview
lastUpdated: 2026-11-05
url: https://dev.duale.ai/en/docs/sdk/troubleshooting
---

## AI-generated summary

This page covers troubleshooting for SDK errors across task outcomes, credentials, libraries, documents, and Tool Host operations.

- Task submission outcomes and model() error handling.
- Credentials and access error resolution.
- Library and document processing failures.
- Tool Host startup, heartbeat, and result errors.
- Support request details to include.

Summaries were generated by AI.

---

Keep `response.task_id` before anything else: you need it to find what happened to the Task. An `AgentResponse` alone
does not prove that Duale AI accepted the Task. Start from what your application observed, then follow the matching
branch. [SDK errors](https://dev.duale.ai/en/docs/sdk/errors.md) lists every exception, field, and code named here.

## Decide what to do when `model()` raises

```mermaid
flowchart TB
    accTitle: Decide what to do when model raises
    accDescr {
      When awaiting response.model raises, keep the Task identifier first. A
      connection error means the SDK lost sight of the Task, not that the Task
      failed, so check before you submit new work. An authentication or
      permission error needs a credential or access fix. A stopped Task needs
      no retry. A validation error means the result did not match your
      response model. For a failed Task, read its problem details: an owner
      action means a configuration change, a retryable failure can be
      submitted again after your own backoff, and any other failure needs a
      changed request.
    }
    Raised["model() raises"]
    Keep[Keep the task_id]
    Conn{DualeAIConnectionError?}
    Lost[Observation failed. The Task can still finish. Check before new work]
    Auth{DualeAIAuthError?}
    Access[Fix the credential or the permission]
    Stopped{TaskStoppedError?}
    Done[Stopped as requested. No retry]
    Invalid{ValidationError?}
    Schema[Align the response model or the instruction]
    Owner{owner_action_required?}
    Config[Ask the configuration owner to change the model pool]
    Retry{retryable is true?}
    Again[Submit again after your own backoff]
    Change[Change the request first]

    Raised --> Keep
    Keep --> Conn
    Conn -- Yes --> Lost
    Conn -- No --> Auth
    Auth -- Yes --> Access
    Auth -- No --> Stopped
    Stopped -- Yes --> Done
    Stopped -- No --> Invalid
    Invalid -- Yes --> Schema
    Invalid -- No --> Owner
    Owner -- Yes --> Config
    Owner -- No --> Retry
    Retry -- Yes --> Again
    Retry -- No --> Change
```

The SDK's own stream recovery has already run when `model()` raises. Any repeat you decide on is new work, with your
own backoff: a failed Task carries no `retry_after_seconds`. This excerpt follows the same order and uses your
`response` and application handlers:

```python
from dualeai import (
    DualeAIAuthError,
    DualeAIConnectionError,
    DualeAIError,
    TaskStoppedError,
    ValidationError,
)

task_id = response.task_id
try:
    result = await response.model()
except DualeAIConnectionError:
    # Observation failed; the Task can still finish. Check before new work.
    record_unobserved_task(task_id)
except DualeAIAuthError:
    fix_credential_or_permission(task_id)
except TaskStoppedError as stopped:
    record_stopped_task(task_id, stopped.reason)
except ValidationError:
    review_response_model(task_id)
except DualeAIError as exc:
    details = exc.problem_details
    if details is not None and details.owner_action_required:
        notify_configuration_owner(task_id, details)
    elif details is not None and details.retryable:
        schedule_resubmission(task_id)  # Your own backoff.
    else:
        change_the_request(task_id, details)
```

**Check.** Each handled branch records the `task_id` and the outcome before your application submits new work.

## Task submission and outcomes

| Symptom                                                 | Cause                                                                                                                                                                                                                                                                                                                               | Fix                                                                                                                                                                                                                                                                                                                                  |
| ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `await response.model()` has not returned when expected | The SDK has not observed a final event; final-answer writing can continue briefly after the deadline.                                                                                                                                                                                                                               | `model()` has no separate timeout. Keep `response.task_id` and allow for that writing ([deadlines](https://dev.duale.ai/en/docs/agent-harness/executors.md#use-one-deadline-for-each-task)). To end the work, request a Stop; to stop waiting only, cancel your local wait ([Observe the Task outcome](https://dev.duale.ai/en/docs/sdk/concepts.md#observe-the-task-outcome)).  |
| `ValidationError` from `model()`                        | The result did not match the response model.                                                                                                                                                                                                                                                                                        | Align the model with the Task, or drop `res` and read the raw completion.                                                                                                                                                                                                                                                            |
| `DualeAIConnectionError` during a Task stream           | Observation failed after recovery attempts or a non-retryable error.                                                                                                                                                                                                                                                                | Read the [stream error context](https://dev.duale.ai/en/docs/sdk/errors.md#task-stream-error-context) and any problem details. Preserve the Task ID; this exception does not prove a failed Task. Check the reported HTTP status or typed cause before repeating work.                                                                                     |
| `error_code` is `CONTENT_FILTERED`                      | No selected model produced an acceptable response; not retryable.                                                                                                                                                                                                                                                                   | Do not retry unchanged. Inspect `problem_details` and adjust the request.                                                                                                                                                                                                                                                            |
| `error_code` is `REQUEST_BLOCKED`                       | A safety check blocked the request that started or continued the Task: it judged that the request tries to make the model ignore its instructions, reveal its instructions or credentials, or speak for the platform, or it failed to judge the request, for example because your model provider refused to read it; not retryable. | Find where the request text came from and remove or rephrase that part. If the request is benign, check whether your model provider filters its subject. Then continue the Task with the complete changed request: later model calls read a notice instead of the blocked one ([Task outcomes](https://dev.duale.ai/en/docs/sdk/errors.md#task-outcomes)). |
| `TASK_DEADLINE_EXCEEDED` with no Tool Call recorded     | The Agent Identity's Tools grew past the bound on what it can hold.                                                                                                                                                                                                                                                                 | Remove an assignment; see [Tool limits](https://dev.duale.ai/en/docs/tools/limits.md#how-many-tools-one-agent-identity-can-hold).                                                                                                                                                                                                                          |
| A submission raises `RuntimeError`                      | The SDK's [circuit breaker](https://dev.duale.ai/en/docs/sdk/errors.md#circuit-breaker) is open after repeated failures.                                                                                                                                                                                                                                  | Wait for the recovery delay, then let one submission check recovery.                                                                                                                                                                                                                                                                 |

## Credentials and access

The SDK obtains a platform token before its first protected request and renews it before expiry. Issuance and
mandatory renewal raise `DualeAIAuthError` for `401`/`403`, or `DualeAIConnectionError` for other failures, including
network errors and unusable responses. A failed early renewal can leave a valid token in use. See [Credentials and
lifecycle](https://dev.duale.ai/en/docs/identity/credentials-and-lifecycle.md) before replacing or revoking the API token.

| Symptom                              | Cause                                                                                                                                       | Fix                                                                                                                                                                                                                                                                                                                                                               |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `DualeAIAuthError` with status `401` | The server rejected the token. On a Library call, `DUALEAI_TENANT_ID` can also name a tenant the token was not issued for, or be malformed. | For a Library call, first check that `DUALEAI_TENANT_ID` is the tenant the token was issued for. Otherwise ask someone with `agent:create_token` to issue a replacement [Agent Identity token](https://dev.duale.ai/en/docs/identity/credentials-and-lifecycle.md), then revoke the old token if still active. Set `DUALEAI_TOKEN` to the replacement, including its `dualeai_` prefix. |
| `ACR_STEPUP_REQUIRED`                | The operation needs a higher authentication level than an API token reaches, such as deleting a whole Library.                              | Use the Dashboard.                                                                                                                                                                                                                                                                                                                                                |
| `DualeAIAuthError` with status `403` | The token's caller lacks the action required by that operation.                                                                             | For a Library call, find the checked action in [Library actions](https://dev.duale.ai/en/docs/sdk/reference.md#library-actions), then correct the Grant or policy. For a Task call, find it in [Task actions](https://dev.duale.ai/en/docs/sdk/reference.md#task-actions). For another operation, verify the caller and its documented access before repeating it.                                            |
| Configuration error at startup       | A required setting is missing or malformed.                                                                                                 | Follow [Exceptions outside the hierarchy](https://dev.duale.ai/en/docs/sdk/errors.md#exceptions-outside-the-hierarchy) and check the [environment variables](https://dev.duale.ai/en/docs/sdk/configuration.md#environment-variables).                                                                                                                                                                        |

## Libraries and documents

| Symptom                                                                               | Cause                                                                                   | Fix                                                                                                                                                                                                                                                                                                          |
| ------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `BusinessError` during a Library call                                                 | The Library rejected the operation with a `4xx`.                                        | Read `problem_details.error_code` and follow its row in [Library request codes](https://dev.duale.ai/en/docs/sdk/errors.md#library-request-codes).                                                                                                                                                                                 |
| `DualeAIConnectionError` while connecting, renewing credentials, or calling a Library | Issuance failed outside `401`/`403`, the network failed, or the Library returned `5xx`. | Check `DUALEAI_ENDPOINT` and [network egress](https://dev.duale.ai/en/docs/sdk/configuration.md#allow-outbound-destinations). If problem details exist, retry only when `retryable` is true. Without problem details, retry safe reads. Before repeating a write whose outcome is unknown, follow that operation's recovery steps. |
| `LibraryUploadError`                                                                  | A local file read or an upload part failed.                                             | Read `attachment_key` and `part_number`; preserve `completed_receipts`, then [recover the partial upload](https://dev.duale.ai/en/docs/sdk/manage-libraries.md#recover-a-partial-upload).                                                                                                                                          |
| `wait_for_document()` returns a `failed` document                                     | The document failed processing.                                                         | Follow its row in [Document ingestion failures](https://dev.duale.ai/en/docs/sdk/errors.md#document-ingestion-failures).                                                                                                                                                                                                           |
| `wait_for_document()` raises `TimeoutError`                                           | The client wait ended; processing can still continue.                                   | Poll the same document with `get_document()`; do not upload it again.                                                                                                                                                                                                                                        |
| A `ready` document preview shows only an encryption type or rights label              | A password or a rights label protects the file.                                         | Duale AI made only that protection metadata searchable. Remove the protection, upload the file again, and confirm that the preview now contains the source text.                                                                                                                                             |
| A `ready` scan or figure gives no visual answer                                       | No configured route carried the picture, or a route limit dropped it.                   | Configure an image-capable Model Route whose limits admit the pictures, then repeat, in a new Task, a question that only one picture answers. [Images in a document](https://dev.duale.ai/en/docs/sdk/attachments.md#images-in-a-document) covers the setup.                                                                       |

## Tool Host

| Symptom                                                                                       | Cause                                                                                                                                                                                                                                                                      | Fix                                                                                                                                                                                                                                          |
| --------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Serving Tools raises an error about `agent_id`                                                | No Agent Identity identifier is configured.                                                                                                                                                                                                                                | Set `DUALEAI_AGENT_ID` to a provisioned Agent Identity before `sdk.serve()`.                                                                                                                                                                 |
| `sdk.serve()` raises `BusinessError` at startup                                               | Duale AI rejected the manifest.                                                                                                                                                                                                                                            | Read `problem_details.error_code` and follow its row in [Tool Host errors](https://dev.duale.ai/en/docs/sdk/errors.md#tool-host-errors).                                                                                                                           |
| One Tool shows **Schema unsupported** and is never offered                                    | A parameter of that Tool has an `alias` that starts with `__`, which Duale AI reserves. `sdk.serve()` raises no error for it.                                                                                                                                              | Give the parameter an `alias` that does not start with `__`, then restart the Tool Host. [Reserved argument names](https://dev.duale.ai/en/docs/tools/limits.md#reserved-argument-names) states the rule.                                                          |
| `@tool` raises `ValueError` when the function is declared                                     | The function uses a reserved Tool name.                                                                                                                                                                                                                                    | Rename the function; [Tool Host errors](https://dev.duale.ai/en/docs/sdk/errors.md#tool-host-errors) lists the reserved names.                                                                                                                                     |
| `sdk.serve()` stops after failed heartbeats                                                   | Three consecutive heartbeats failed, for example with `RATE_LIMIT_EXCEEDED` when several processes serve one Agent Identity, or two were refused with `401` or `403`.                                                                                                      | Run one Tool Host process per Agent Identity. For a refusal, check the token and its `agent:heartbeat` permission. Then restart `serve()`.                                                                                                   |
| A Tool Result submission fails with `REQUEST_BODY_TOO_LARGE`                                  | The result is larger than one submission accepts.                                                                                                                                                                                                                          | Return identifiers, summaries, or rows instead; see [Keep the Tool Result small](https://dev.duale.ai/en/docs/sdk/tools.md#keep-the-tool-result-small).                                                                                                            |
| Built-in `TimeoutError` from an `@activity`                                                   | The wait for scheduled activity work exceeded `job_timeout`.                                                                                                                                                                                                               | Treat the Effect as uncertain. Cancellation cannot roll back an external action that already completed. [Activity caching](https://dev.duale.ai/en/docs/sdk/activity-caching.md) explains the timer.                                                               |
| The answer says that a safety check blocked a step, and your function returned a result       | A safety check judged that the Tool Result tries to instruct the model, for example to drop its Task or reveal its instructions, or it failed to judge the result. The Tool ran; later model calls read a notice instead of its result, and the Task continued without it. | Return data, not instructions to the model. If the result is benign, check whether your model provider filters its subject. When the Tool passes on content you do not control, such as emails or web pages, this outcome protects the Task. |
| The answer says that a safety check blocked a step, and your function never received the call | A safety check judged that the Tool Call has an effect the Task's request does not explain, such as sending data to a recipient the request does not name, or it failed to judge the call. Duale AI did not send the call, and the model read that it was blocked.         | Name in the request the recipients, destinations, and changes the work needs, then continue the Task.                                                                                                                                        |

## Ask for support

If a failure persists, email [technical support](mailto:contact+support@mail.duale.ai) with the `task_id`, the
`error_code`, the `trace_id` and `span_id` when present, the `request_id` for an HTTP rejection, and the stream
context's `operation`, `retry_attempt`, and HTTP status. Never send the API token or a platform token.

## Related content

- [SDK exceptions, problem details, and error codes](https://dev.duale.ai/en/docs/sdk/errors.md)
- [SDK concepts: Task lifecycle, outcomes, and continuations](https://dev.duale.ai/en/docs/sdk/concepts.md)
- [Tools troubleshooting: catalog, calls, recovery](https://dev.duale.ai/en/docs/tools/troubleshooting.md)
- [Manage Libraries: create, upload, and verify ingestion](https://dev.duale.ai/en/docs/sdk/manage-libraries.md)
- [SDK configuration: variables, egress, logging, telemetry](https://dev.duale.ai/en/docs/sdk/configuration.md)
- [SDK reference: ask, next, AgentResponse, stop_task](https://dev.duale.ai/en/docs/sdk/reference.md)

---

## Sitemap

See the full [Markdown sitemap](https://dev.duale.ai/sitemap.md) for all pages.
