# Erros

> Todo erro da API do Nodaro tem status HTTP e código estável em um envelope. Veja o que cada código significa, quais repetir e como jobs relatam falhas.

Source: https://nodaro.ai/pt-BR/docs/developers/api/errors

Todo **erro da API do Nodaro** retorna um status HTTP e um envelope JSON com um `code` estável, para que o seu cliente decida o tratamento pelo código em vez de analisar mensagens. Há dois tipos de falha. Um **erro de requisição** acontece quando a própria chamada é recusada e nada começa. Uma **falha de job** acontece quando uma geração que começou falha depois e informa o motivo no job.

## O envelope de erro
```json
{ "error": { "code": "rate_limited", "message": "Too many requests. Max 30 per minute." } }
```

- `code` é um slug estável. Decida o tratamento por ele.
- `message` é um texto para pessoas. Ele pode mudar, então nunca use esse texto em comparações.
- Alguns erros adicionam campos, listados com cada código abaixo. A maioria fica dentro de `error`. `already_running` coloca `executionId` ao lado de `error`, e uma verificação de limite de uso que falha antes da execução coloca `required` e `remaining` no nível superior.

O endpoint de token do OAuth é a única exceção: ele responde no formato do OAuth, por exemplo `{ "error": "invalid_grant", "error_description": "…" }`. Veja [Apps OAuth](https://nodaro.ai/docs/developers/oauth).

## Quais erros tentar de novo
| Status | O que fazer |
| --- | --- |
| `5xx` | Normalmente temporário. Tente de novo com backoff exponencial. |
| `429` | Espere e tente de novo com backoff: por exemplo, 5, depois 10, depois 20 segundos. Respeite o cabeçalho `Retry-After` quando ele existir. |
| `402` | Adicione créditos, ou peça orçamento a um administrador do espaço de trabalho, e tente de novo. |
| Outros `4xx` | Corrija a requisição primeiro. A mesma requisição falha de novo. |

Três erros de servidor exigem cuidado:

- `503 price_not_configured` não dá certo em uma nova tentativa: o modelo não tem preço nesta implantação até o operador dela definir um.
- `503 provider_unavailable` na rota assíncrona de saída estruturada de LLM é permanente em uma instalação que envia as chamadas de modelos de linguagem para o nodaro.ai.
- Na publicação em redes sociais, `503 publish_retryable` significa que nada foi publicado e que é seguro enviar a mesma requisição de novo. Já `500 publish_failed` significa que o resultado é desconhecido, e enviar de novo pode publicar duas vezes.

## Códigos de erro
### 400 Bad Request
| Código | Significado |
| --- | --- |
| `validation_error` | Um corpo malformado, um UUID inválido, um campo inválido ou um cursor malformado. |
| `limit_reached` | Você já tem 10 tokens de API, ativos ou não. Exclua um primeiro. |
| `invalid_workflow` | Uma entrada de `workflowIds` de um token não é um workflow do seu espaço pessoal. |
| `token_workspace_mismatch` | Um token vinculado a um espaço de trabalho foi enviado com um cabeçalho `X-Nodaro-Workspace` que indica outro. |
| `locked_field` | Uma execução tentou mudar para onde um nó externo envia dados ou de onde ele os busca. Veja [O que uma execução não pode mudar](https://nodaro.ai/docs/developers/api/workflows#what-a-run-cannot-change). |
| `image_required` | `POST /v1/generate-video` sem quadro inicial, em um modelo que não consegue fazer vídeo a partir de texto. A mensagem diz se referências funcionariam no lugar dele. |
| `sequence_execution_required` | A execução inclui nós de produção do Studio que precisam ser gerados pela API de produções do Studio. |
| `not_workspace_scoped` | Você mudou `visibility` em um workflow que não está em um espaço de trabalho. |
| `advanced_mode_unsupported` | `advancedMode: true` em um modelo que não tem uma via direta. |

### 401 Unauthorized
| Código | Significado |
| --- | --- |
| `unauthorized` | O token está ausente, é inválido, expirou ou foi revogado. |

### 402 Payment Required
Estes códigos vêm do Nodaro Cloud e das implantações que fazem cobrança.

| Código | Campos extras | Significado |
| --- | --- | --- |
| `insufficient_credits` | `required`, `balance` | A conta ficou sem créditos. Em uma implantação com uma única conta de cobrança, significa que o saldo compartilhado da implantação está vazio: o erro então traz `required`, mas nunca `balance`, e só a conta de cobrança pode adicionar créditos. |
| `insufficient_app_credits` | | A execução de um app publicado: a conta ficou sem créditos. |
| `budget_exceeded` | | Trabalho pago por um espaço de trabalho: o orçamento do espaço de trabalho não cobre a execução. Peça mais a um administrador do espaço de trabalho. |
| `member_cap_exceeded` | | Trabalho pago por um espaço de trabalho: o seu próprio limite de gastos nesse espaço de trabalho foi atingido. |
| `user_allowance_exceeded` | `required`, `remaining` | Uma implantação com uma única conta de cobrança que aplica limites de uso por usuário: o seu limite de uso não cobre a execução. Só a conta de cobrança pode aumentá-lo. |
| `instance_cap_reached` | | Um token OAuth de uma instalação self-hosted conectada: a instalação gastou o limite mensal dela na conta que a conectou. Aumente ou remova o limite em **Instâncias conectadas**. |

### 403 Forbidden
| Código | Campos extras | Significado |
| --- | --- | --- |
| `forbidden` | | O escopo de workflows do token não inclui este workflow, ou a rota precisa de uma sessão com login. Veja [Autenticação](https://nodaro.ai/docs/developers/api/authentication#routes-that-need-a-signed-in-session). |
| `insufficient_scope` | `missingScope` | Um token OAuth não tem um escopo de que a rota precisa. Peça de novo o consentimento do usuário, com o escopo mais amplo. |
| `in_app_only` | | A rota existe só para o app web do Nodaro, como o Workflow Copilot. |
| `node_not_available` | | Esta implantação não oferece à sua conta o nó, ou a opção que você escolheu nele. A mensagem diz qual é. Nada é cobrado. |
| `model_not_available` | | O `provider` que você enviou indica um modelo que esta implantação não oferece. Escolha outro modelo. Nada é cobrado. |
| `edition_required` | `required_edition` | A rota precisa de uma edição superior: `cloud` para a derivação de pipelines, `business` para o gerenciamento de tokens de API. |
| `not_a_member` | | O cabeçalho `X-Nodaro-Workspace` indica um espaço de trabalho do qual você não é membro ativo. |
| `member_suspended` | | A sua participação no espaço de trabalho está suspensa. |
| `personal_space_disabled` | | A sua organização só permite criar trabalho dentro de um espaço de trabalho. Envie o cabeçalho do espaço de trabalho. |
| `project_create_not_allowed` | | Só os administradores do espaço de trabalho podem criar projetos. |
| `workspace_archived` | | Uma escrita em um espaço de trabalho arquivado, como compartilhar um workflow. Criar trabalho nele responde `409` em vez disso. |
| `not_permitted` | | Você não pode mover este workflow, ou não pode movê-lo para esse destino. |
| `sso_required` | | A implantação restringe o login ao provedor de identidade dela, e a conta desta sessão não foi criada por ele. Os tokens não são afetados. |
| `subscription_required` | | Uma conta de pagamento por uso tentou gastar créditos pelo editor web. Os créditos do pagamento por uso funcionam pela API, pelo SDK, pela CLI e pelo MCP, então as chamadas com token nunca recebem este código. |
| `api_tokens_payer_only` | | Em uma implantação com uma única conta de cobrança, só essa conta pode criar tokens de API. |
| `payer_balance_jwt_only` | | Em uma implantação assim, a conta de cobrança leu o saldo compartilhado com um token. Só a própria sessão do navegador dela pode fazer isso. |
| `payer_required` | | Uma rota de cobrança da implantação foi chamada por algo que não é a sessão do navegador da conta de cobrança. |

### 404 Not Found
| Código | Significado |
| --- | --- |
| `not_found` | O recurso não existe, ou você não pode vê-lo. As duas situações têm deliberadamente a mesma resposta, para que um ID nunca revele se algo existe. |
| `workspace_not_found` | Um trabalho pago por um espaço de trabalho indica um espaço de trabalho que não existe. |

### 409 Conflict
| Código | Campos extras | Significado |
| --- | --- | --- |
| `already_running` | `executionId` | O workflow já tem uma execução ativa. Em vez disso, consulte essa execução periodicamente. |
| `workflow_conflict` | `currentVersion`, `currentUpdatedAt`, `currentRecord` | O workflow mudou desde a versão que você enviou. Mescle as suas mudanças com `currentRecord` e salve de novo. |
| `workspace_archived` | | Você tentou criar ou mover trabalho para um espaço de trabalho arquivado. |
| `workspace_has_no_default_project` | | Uma criação em um espaço de trabalho não indicou nenhum projeto, e o espaço de trabalho não tem nenhum. Indique um projeto. |
| `move_blocked` | | O trabalho foi criado para uma atividade e não pode ser movido. |
| `production_capability_required` | | Um salvamento genérico de workflow alterou uma produção do Studio que precisa da própria API. |
| `retained_image_in_use` | | Uma exclusão removeria imagens protegidas, ou uma produção ainda tem jobs usando essas imagens. Termine ou cancele esses jobs primeiro. |

### 413, 422 e 429
| Status | Código | Significado |
| --- | --- | --- |
| 413 | | A sua conta passou do limite de armazenamento. O SDK lança `StorageExceededError` com `limitBytes`. |
| 422 | `job_blocked` | A política de jobs da implantação recusou a geração antes da execução. Nenhum job foi criado e nada foi cobrado. Mostre `message` ao seu usuário como está e não repita a mesma requisição. |
| 422 | `upload_blocked` | A política de upload da implantação recusou um arquivo antes de ele ser armazenado. Mostre `message` como está. |
| 422 | `offsets_not_applied` | O `POST /v1/edit-plan` recebeu um campo `offsets` bruto. Grave antes cada deslocamento na origem dele, como `sources[].offsetMs`. Veja [Plano de edição](https://nodaro.ai/docs/nodes/video/edit-plan#api). |
| 422 | `master_offset` | O `POST /v1/edit-plan` recebeu um deslocamento diferente de 0 na origem mestre, ou na origem a partir da qual a transcrição foi feita. Nada é cobrado. |
| 429 | `rate_limited` | O limite por token de um token de API pessoal. |
| 429 | `rate_limit_exceeded` | Qualquer outro limite: por endereço, por rota ou as execuções diárias de um app publicado. |
| 429 | `too_many_downloads` | Você já tem 4 importações de vídeo em andamento. |

Os códigos `job_blocked` e `upload_blocked` só acontecem em implantações que registram uma política desse tipo. Veja [Limites de taxa](https://nodaro.ai/docs/developers/api/rate-limits) para os códigos `429`.

### 500 e 503
| Status | Código | Significado |
| --- | --- | --- |
| 500 | `internal_error` | Um erro do servidor ou uma falha de um serviço do qual ele depende. Tente de novo com backoff. |
| 503 | `price_not_configured` | O modelo solicitado não tem preço nesta implantação, então o servidor recusa em vez de cobrar errado. Tentar de novo não adianta. |
| 503 | `rate_limit_unavailable` | Uma rota que gasta créditos não conseguiu verificar o limite de taxa dela. Tente de novo mais tarde. |
| 503 | `provider_unavailable` | O provedor do modelo não está disponível. |
| 503 | `billing_unavailable` | O relatório de uso ainda não está disponível nesta instância. |

## Quando um job falha depois
Uma requisição bem-sucedida ainda pode produzir um job que falha. O job então traz `error_message` e, em dois tipos de falha, um `error_hint` estruturado:

- `{ "kind": "safety-block", "class": "copyright" | "likeness" | "safety", "retried": boolean, "suggestedProvider"?: string }` quando o filtro de segurança de um modelo bloqueou a requisição.
- `{ "kind": "policy-block", "policyId": string, "reason": string, "hookPoint": "request" | "result" }` quando a política de uma implantação rejeitou a requisição.

Os dois casos são sempre reembolsados, e o `credit_status` do job mostra isso. Leia [Por que um job falhou](https://nodaro.ai/docs/developers/api/jobs#why-a-job-failed) para saber o que cada campo significa e quando tentar outro modelo.

## Erros no SDK
O `@nodaro/sdk` lança um erro tipado para cada resposta com falha. Capture primeiro a classe mais específica:

| Classe | Status | Campos extras |
| --- | --- | --- |
| `UnauthorizedError` | 401 | |
| `ForbiddenError` | 403 | `missingScope` quando o código é `insufficient_scope` |
| `NotFoundError` | 404 | |
| `InsufficientCreditsError` | 402 | `required`, `available` |
| `StorageExceededError` | 413 | `limitBytes` |
| `WorkflowConflictError` | 409 | `currentVersion`, `currentUpdatedAt`, `currentRecord`. Também usado no conflito `production_busy` do Studio. |
| `RateLimitedError` | 429 | |
| `JobBlockedError` | 422 | |
| `StudioOpError` | 4xx | `opIndex`: qual operação de um lote do Studio foi recusada |
| `NodaroError` | qualquer | A classe base: `code`, `status` e `message` |

```ts

NodaroError,
ForbiddenError,
InsufficientCreditsError,
RateLimitedError,
} from '@nodaro/sdk'

try {
await client.workflows.run(workflowId)
} catch (err) {
if (err instanceof InsufficientCreditsError) {
showPaywall({ required: err.required, available: err.available })
} else if (err instanceof ForbiddenError && err.missingScope) {
requestConsent([err.missingScope])
} else if (err instanceof RateLimitedError) {
await new Promise((r) => setTimeout(r, 5_000))
} else if (err instanceof NodaroError) {
console.error(`API error ${err.status} (${err.code}): ${err.message}`)
} else {
throw err // a network failure, not an API error
}
}
```

As funções auxiliares de consulta periódica adicionam erros próprios, como `JobFailedError` e `JobTimeoutError`. Veja [Executar um único nó](https://nodaro.ai/docs/developers/api/nodes#example-generate-an-image).

## Erros na CLI
| Código de saída | Significado |
| --- | --- |
| `0` | Sucesso. |
| `1` | Não autorizado, não encontrado, um argumento errado ou um erro de rede. |
| `2` | O `--watch` terminou e a execução falhou. |
| `3` | O `--watch` parou porque o job está retido para revisão. Não é uma falha: verifique de novo mais tarde. |
| `130` | O `--watch` terminou e a execução foi cancelada. |

Com `--json`, a CLI imprime o payload e sai normalmente em vez de usar os códigos 2, 3 e 130, então verifique `.status` você mesmo.

## Frequently asked questions

### Como é um erro da API do Nodaro?

Todo erro tem um status HTTP e o corpo { "error": { "code": "…", "message": "…" } }. O código é estável, então baseie o tratamento nele. A mensagem é para pessoas e pode mudar.

### Quais erros da API do Nodaro devo tentar de novo?

Tente de novo os erros 5xx e o 429 com backoff exponencial, por exemplo depois de 5, 10 e 20 segundos. Não repita uma requisição que deu erro 4xx sem mudá-la, porque a mesma requisição falha de novo. Entre os erros de servidor, 503 price_not_configured é a exceção.

### O que significa 402 insufficient_credits?

A conta não tem créditos suficientes para iniciar a execução. O erro traz required, os créditos de que a execução precisa, e normalmente balance. Adicione créditos no Nodaro Cloud e envie a requisição de novo.

### O que é error_hint em um job com falha?

É um motivo estruturado anexado a um job com falha em dois tipos de falha: o filtro de segurança de um modelo e a política de uma implantação. Leia esse campo em vez de analisar error_message, por exemplo para oferecer o modelo sugerido.

### Por que uma rota responde 403 in_app_only?

A rota existe só para a sessão do próprio app web do Nodaro, por exemplo o Workflow Copilot ou as credenciais salvas da Saída de webhook. Tokens de API e tokens OAuth não podem chamá-la. Em vez disso, use os endpoints de workflow, o SDK ou o MCP.
