Errores
Los errores son JSON, como todo lo demás, con un estado HTTP que coincide y un código sobre el que puedes ramificar tu lógica. El mensaje es una frase pensada para tus registros, no para tus usuarios; su redacción puede cambiar, el código nunca.
El sobre de error
{
"status": "error",
"error": {
"code": "invalid_request",
"message": "Parameter 'lat' must be a number between -90 and 90.",
"param": "lat"
}
}param aparece cuando un parámetro concreto causó el problema. X-Request-Id también se incluye en las respuestas de error; indícalo si contactas con soporte.
Códigos
| HTTP | code | Cuándo | Qué hacer |
|---|---|---|---|
| 400 | invalid_request | Falta un parámetro obligatorio, un valor está mal formado o fuera de rango, hay más de 100 puntos o direcciones en un lote, o se piden más de 10 resultados. | Corrige la solicitud. No la reintentes sin cambios. |
| 401 | missing_key | No se envió ninguna clave y el acceso sin clave está desactivado en este servidor. Por defecto está activado, y una solicitud sin clave simplemente se responde. | Envía una clave como X-API-Key, como token bearer o como key=. |
| 429 | quota_exceeded | La dirección ha usado sus 2.500 solicitudes gratuitas del día sin clave. | Espera al reinicio (Retry-After y X-Quota-Reset indican cuándo), o envía una clave con crédito o con un paquete Unlimited. |
| 401 | invalid_key | La clave no existe. | Comprueba si hay errores tipográficos o si la copia está truncada. |
| 401 | key_revoked | La clave se revocó en el panel. | Usa una clave vigente. |
| 402 | no_credits | La cuota gratuita del día de la clave está agotada y el saldo de crédito de la cuenta está vacío. | Añade crédito en el panel, con tarjeta o criptomonedas, o espera al reinicio. |
| 403 | key_ip_limit | Todos los espacios de IP de esta clave están ocupados por otras direcciones durante un tiempo. | Usa una de las máquinas que ocupan los espacios, dale a esta máquina su propia clave o añade un paquete. Consulta espacios de IP. |
| 403 | account_suspended | La cuenta está suspendida. | Revisa nuestros correos o abre un ticket. |
| 404 | not_found | La ruta no existe. Una consulta sin coincidencias es 200 con resultados vacíos, no 404. | Comprueba la ruta y el prefijo de versión. |
| 500 | server_error | Algo falló por nuestra parte. | Reintenta una vez tras un segundo. Queda registrado y nos alerta. No se contabiliza. |
| 503 | unavailable | Un backend no está disponible temporalmente. | Reintenta con espera progresiva. No se contabiliza. |
Cosas que no son errores
- Sin resultados. Una geocodificación directa de un texto sin sentido devuelve
200con"results": []. Una geocodificación inversa en el océano devuelve200con"result": null. Ambas cuentan como solicitud. - Baja precisión. Un resultado con
"precision": "admin"cuando querías un número de casa es una solicitud correcta que encontró menos de lo que esperabas. Revisa el campo. - Direcciones IP privadas. Consultar
10.0.0.1devuelve200con"is_private": truey sin ubicación.
Errores en los hosts compatibles
Los hosts de compatibilidad devuelven los errores con la estructura que usa el proveedor original, así que tu gestión actual funciona. Por ejemplo, un saldo de crédito vacío es "status": "OVER_QUERY_LIMIT" con HTTP 200 en gapi.mygeocode.com, "statusCode": 429 en el sobre de Bing en bing.mygeocode.com, y {"status":"fail","message":"quota"} en ipapi.mygeocode.com; una clave incorrecta es REQUEST_DENIED, 401 e invalid key respectivamente. Las cabeceras X-Quota-* se envían en todos los hosts en cualquier caso, así que puedes leer el estado real en las cabeceras si quieres.
Una estrategia de gestión razonable
def call(url, params, tries=3):
for attempt in range(tries):
r = session.get(url, params=params, timeout=10)
if r.status_code == 200:
return r.json()
body = r.json()
code = body["error"]["code"]
if r.status_code in (500, 503):
time.sleep(0.2 * (2 ** attempt))
continue
# no_credits, key_ip_limit, invalid_request, invalid_key: retrying will not help
raise ApiError(code, body["error"]["message"], r.headers.get("X-Request-Id"))
raise ApiError("retries_exhausted", "Gave up after %d attempts" % tries, None)