Guías
Errores
Un error de herramienta es un resultado con isError: true y el problema en el primer bloque de texto. Ramifica por su code.
La forma de un error
Enlace a esta sección: La forma de un errorEl servidor informa de una llamada fallida como un resultado, no como un error JSON-RPC. El resultado lleva isError: true y el problema RFC 9457 de la API REST como JSON en content[0].. No lleva structuredContent: la especificación exige que structuredContent coincida con el outputSchema de la herramienta, y un error no lo cumple.
{
"isError": true,
"content": [
{
"type": "text",
"text": "{\"type\":\"https://docs.filmo.io/errors/rate_limited\",\"title\":\"Rate limit exceeded\",\"status\":429,\"code\":\"rate_limited\",\"detail\":\"Rate limit exceeded: retry in 17 seconds\",\"requestId\":\"req_…\",\"retryAfter\":17,\"meta\":{\"rateLimit\":{\"limit\":120,\"remaining\":0,\"reset\":17}}}"
}
]
}El problema incluye type, title, status, code, detail, requestId y, cuando corresponden, errors[], requiredScope, requiredAddon y retryAfter. Una llamada con clave de idempotencia también devuelve meta. dentro del problema. Cita requestId cuando pidas ayuda. Es el mismo documento de problema que devuelve la API REST: consulta Errores.
Errores de protocolo
Enlace a esta sección: Errores de protocoloUna petición mal formada, un método desconocido o una herramienta desconocida es un error JSON-RPC con un código como -32600, -32601, -32602 o -32700, y su mensaje está en inglés. Una llamada sin credencial no es JSON-RPC: es un HTTP 401 con un cuerpo de problema. Consulta la referencia del protocolo.
Leer un error con los SDK oficiales
Enlace a esta sección: Leer un error con los SDK oficialesClient. del SDK de TypeScript y call_tool del SDK de Python devuelven el resultado; ninguno lanza una excepción por un error de herramienta. Comprueba isError y analiza el primer bloque de texto. Solo los fallos de protocolo, como una herramienta desconocida o un timeout, lanzan excepción.
const result = await client.callTool({ name, arguments: args });
if (result.isError) {
const text = (result.content as { type: string; text?: string }[]).find((c) => c.type === "text")?.text ?? "{}";
const problem = JSON.parse(text); // { code, status, detail, requestId, retryAfter?, requiredScope? }
if (problem.code === "rate_limited") await sleep(problem.retryAfter * 1000);
}import asyncio, json
async def call(session, name, args):
result = await session.call_tool(name, arguments=args)
if result.isError:
problem = json.loads(result.content[0].text) # code, status, detail, requestId, retryAfter?, requiredScope?
if problem["code"] == "rate_limited":
await asyncio.sleep(problem["retryAfter"])
return resultEn los paquetes 2.x el campo es is_error en Python y el transporte se construye de otra forma; el contrato del servidor es el mismo. Consulta Construir tu propio cliente.
Ramificar según el código
Enlace a esta sección: Ramificar según el código| Código | Estado | Qué hacer |
|---|---|---|
unauthorized | 401 | Envía una credencial. Los códigos api_key_* indican por qué una clave no es válida: revocada, caducada o su propietario ya no es administrador. |
insufficient_scope | 403 | A la clave o a la conexión le falta requiredScope. Mira más abajo. |
validation_error | 400 | Corrige los campos indicados en errors[] y vuelve a llamar. |
not_found | 404 | El registro no existe en esta cuenta. |
conflict | 409 | Lee errors[0]. para saber la causa; vuelve a leer el registro antes de reintentar. |
precondition_failed | 412 | El registro cambió desde que lo leíste. Vuelve a leerlo. |
idempotency_key_reused | 422 | Esa clave se usó con argumentos distintos. Usa una clave nueva. |
rate_limited | 429 | Espera retryAfter segundos. |
addon_required | 402 | La cuenta necesita el add-on indicado en requiredAddon. |
service_unavailable | 503 | La función está desactivada para la cuenta; reintentar no sirve de nada. |
Permiso insuficiente
Enlace a esta sección: Permiso insuficienteUna herramienta que necesita un permiso (scope) que la conexión no tiene devuelve insufficient_scope con requiredScope. El servidor no responde con un 403 que pida al cliente ampliar sus permisos, así que ningún cliente añade el permiso por sí solo. Para añadir uno, elimina el conector y vuelve a añadirlo, y marca el permiso en la pantalla de consentimiento. Con una clave, crea otra clave con el permiso.
Reintentos
Enlace a esta sección: ReintentosSe aplica la tabla de decisión de la API REST. Un resultado te indica que es una repetición con meta..
| Estado | Idempotency-Key | Idempotent-Replay: true | Qué hacer |
|---|---|---|---|
| 409 conflict · in_progress | Sí | No | errors[0]. es in_progress: otra petición con la misma Idempotency-Key sigue en curso. Espera y reintenta con la misma clave (espera exponencial, hasta 3 veces): recibirás su respuesta guardada cuando termine. |
| 409 conflict · lock_timeout | — | No | errors[0]. es lock_timeout: otra escritura condicional retuvo el recurso más de 5 s. Reintenta con la misma clave y espera exponencial, hasta 3 veces; si persiste, vuelve a leer el recurso. |
| 409 conflict · invalid_state | — | — | errors[0]. es invalid_state: el estado del recurso impide la operación (una violación de unicidad, una línea de un lote atómico). No reintentes: esperar no lo arregla nunca. Vuelve a leer el recurso y decide según su estado actual. |
| 409 contact_in_use · address_in_use · insufficient_stock | — | — | No reintentes. errors[] dice qué bloquea la operación: corrígelo primero. |
| 412 precondition_failed | — | — | Vuelve a leer el recurso, rehaz tu cambio sobre él y envía el ETag nuevo. |
| 422 idempotency_key_reused | Sí | — | Es un fallo del cliente: la clave se usó con otro cuerpo. Usa una clave nueva solo si de verdad es otra operación. |
| 429 rate_limited | — | — | Espera los segundos de Retry-After y reintenta con la misma clave. |
| 500 internal_error | Sí | Sí | Para. El fallo ocurrió después del commit y se guarda y se repite durante 24 h con esa clave: lee el recurso para ver dónde quedó. |
| 500 internal_error | Sí | No | Reintenta con espera exponencial y la misma clave. |
| 500 internal_error | No | — | Lee antes de reintentar una escritura: sin clave nada te protege de un duplicado. |
| 503 service_unavailable | — | — | No reintentes: la función está desactivada en la cuenta. |
207 (returnOrderLineItems con atomic: false) | Sí | — | Las líneas que fallaron no se devolvieron y el resto sí. Reenvía solo las fallidas con una clave nueva; repetir la clave devolvería el mismo 207. |
413 · 502 · 504 (no es application) | Sí | — | Respuesta de la plataforma, no de la API: decide por el estado y reintenta con la misma clave. Un 413 no se arregla reintentando (el cuerpo es demasiado grande). |
| Cualquier 4xx de validación | — | — | Corrige la petición y reenvíala; nunca en bucle. |
| 401 · 402 · 403 (clave, propietario o plan) | — | — | No reintentes: reenviar la misma petición vuelve a fallar. Actúa sobre la clave, su propietario o el plan: usa una clave válida con el permiso adecuado, pide a un administrador el permiso que falta o contrata el add-on. |
Cada código de error tiene su propia página en la pestaña de la API REST, con cuándo ocurre y qué hacer.
Páginas relacionadas
Enlace a esta sección: Páginas relacionadasGuías
Escrituras seguras
Un asistente que puede escribir también puede escribir lo equivocado. Decide qué herramientas necesitan a una persona, reintenta sin duplicar y sabe qué pone en marcha una escritura.
Referencia
Referencia del protocolo
Lo que necesita un cliente para hablar con el servidor sin uno hecho.
¿Te ha resultado útil esta página?