Saltar a contenido

Errores

Los códigos y mensajes que devuelve kubelatch, qué significan y qué hacer con cada uno. kubectl y la API los reciben en inglés; la interfaz muestra los errores de la API en tu idioma.

Errores del proxy

El proxy (/clusters/<id>/...) responde siempre con un objeto Status de Kubernetes, así que kubectl muestra el mensaje directamente:

{"kind": "Status", "apiVersion": "v1", "status": "Failure", "message": "credential revoked", "reason": "Unauthorized", "code": 401}

Toda respuesta del proxy lleva la cabecera Audit-ID. Si abres una incidencia, incluye ese valor. Las respuestas de la API llevan X-Request-Id en su lugar (ver Errores de la API).

Código Mensaje Qué significa Qué hacer
400 invalid path: empty segments, '.' or '..' or escaped characters are not allowed La ruta tiene //, ., .., un escape o un %. Revisa el server del kubeconfig: debe ser https://<kubelatch>/clusters/<id>, sin nada más.
400 invalid cluster identifier: … El segmento tras /clusters/ no puede ser el id de un cluster. Usa el kubeconfig que te dio kubelatch.
400 kubelatch does not accept Impersonate-* headers (kubectl --as is not supported) Usaste --as, --as-group o una herramienta que usa la suplantación. Quita --as. Si necesitas probar permisos de otro, usa el acceso nativo de administración.
401 a kubelatch token is required (Authorization: Bearer klt_...) No hay token, o no tiene el formato de un token de kubelatch. Comprueba que el kubeconfig tiene el token completo.
401 unknown credential El token no existe en kubelatch (mal copiado, de otra instalación, o su cluster se borró). Emite una credencial nueva.
401 credential revoked Alguien revocó la credencial. Emite una nueva; si no fuiste tú, avisa a un admin.
401 credential expired Pasó su fecha de caducidad. Renueva la credencial.
401 this credential is only valid on the MCP endpoint El token es de una sesión de agente; solo funciona en /mcp. Usa una credencial tuya para kubectl; deja el token del agente para el agente.
403 the account is disabled La cuenta dueña de la credencial está deshabilitada. Habla con un admin.
403 this credential is restricted to cluster <id> La credencial se emitió para otro cluster. Usa el contexto correcto o emite una credencial para este cluster.
403 <user> has no active permissions on cluster <id> No tienes ningún permiso vigente en ese cluster (nunca lo tuviste, se revocó o caducó). <user> es el nombre que te da el cluster: user:<login> por defecto, o lo que rinde su plantilla de identidad. El mensaje termina diciendo dónde pedir acceso (403 — sin permiso). Pide el permiso donde dice esa frase.
403 this cluster identifies people by their verified e-mail and the account `<login>` has none: sign in with the identity provider, or ask an administrator to link it El cluster nombra a las personas con algo que tu cuenta no tiene: el correo verificado de tu identidad en el proveedor OIDC, como aquí, o su sujeto (their identity provider subject) o tu login de GitHub vinculado (their GitHub login). Entra una vez en kubelatch con el proveedor de identidad, o vincula GitHub; un admin también puede mandarte un enlace de vinculación (Cuentas que no se pueden nombrar).
403 the name this cluster would give the account `<login>` is not valid: ask an administrator La plantilla de identidad del cluster da a tu cuenta un nombre que el cluster no debe recibir, como uno que empieza por system: o lleva un espacio. Un admin cambia la plantilla o la cuenta.
403 the credential is no longer valid: revoked, expired, account disabled or permissions changed La petición estaba en curso y se cortó porque algo cambió. Vuelve a lanzarla; si sigue fallando, mira las filas anteriores.
404 unknown cluster No hay ningún cluster con ese id. Revisa el server del kubeconfig.
500 internal error Fallo inesperado de kubelatch. Busca el Audit-ID en el log de kubelatch.
502 could not talk to the cluster's API server: timed out El API server no respondió a tiempo. Un admin debe revisar la red entre kubelatch y el cluster.
502 could not talk to the cluster's API server: the API server certificate does not match the registered CA El certificado del API server cambió o no es el registrado. Un admin reenrola el cluster («Reenrolar») con el kubeconfig actual del cluster: el comando de enrolamiento trae la CA nueva.
502 could not talk to the cluster's API server: API server unreachable Conexión rechazada, nombre sin resolver o red inalcanzable. Un admin comprueba la URL del cluster y la ruta de red (ver Clusters privados).
502 could not talk to the cluster's API server: connection error Otro fallo de conexión. El detalle completo está en el log de kubelatch.
503 the cluster has no tokens configured yet El cluster está registrado pero falta ejecutar su comando de enrolamiento (o pegar el JSON del bootstrap). Un admin termina el registro del cluster.
503 kubelatch cannot query its database Postgres no responde, o (si solo pasa en un cluster) sus tokens no se pueden descifrar porque cambió KUBELATCH_ENCRYPTION_KEY; el log dice proxy: load cluster. Un admin revisa Postgres o rota los tokens del cluster.
503 kubelatch cannot record the request No se pudo escribir la fila de auditoría; sin ella la petición no se reenvía. Un admin revisa Postgres.
503 kubelatch is restarting La réplica se está apagando (un rollout). Reintenta: kubectl y client-go lo hacen solos.

Un 403 con un mensaje del estilo User "user:<login>" cannot list resource "secrets"… no es de kubelatch: es el RBAC del cluster diciendo que tu rol no incluye esa acción (ver Roles y Roles de sistema). Cuando kubelatch conoce un rol que lo permitiría, añade al final una frase, kubelatch: the <role> role … allows this., y dónde pedirlo (403 — sin permiso). Con un rol nativo, lo que permite el rol es lo que los bindings propios del cluster dan a sus grupos. Un 403 que dice que kubelatch-proxy no puede suplantar tu nombre o un grupo significa que la reconciliación dejó fuera ese nombre: lo comparten dos cuentas, el cluster lo enlaza a cluster-admin y algún permiso no caduca en 8 horas como máximo, o la pasada aún no ha llegado. La página del cluster dice cuál (Identidad en el cluster).

El endpoint MCP

/mcp, donde se conectan los agentes de IA, responde sus propios rechazos en texto plano, no como un Status. Una herramienta que llega a un cluster pasa por el proxy, y el agente recibe en el error de la herramienta el código y el mensaje del proxy de la tabla anterior, con su id de auditoría. Todo 401 lleva WWW-Authenticate: Bearer resource_metadata="<KUBELATCH_BASE_URL>/.well-known/oauth-protected-resource/mcp", que indica a un cliente MCP dónde iniciar sesión.

Código Mensaje Qué significa Qué hacer
400 JSON-RPC batches are not accepted El cliente envió varios mensajes JSON-RPC en un array. Envía un mensaje por petición, como hacen los clientes MCP actuales.
401 invalid token: … La comprobación del token rechazó la petición; el resto es el mensaje del proxy, como invalid token: credential revoked, o invalid token: this agent session was revoked cuando tú o un admin cortasteis la sesión del agente. Lo mismo que para ese mensaje en el proxy.
401 invalid token: the MCP endpoint accepts a bot's credential, or an agent's token from kubelatch's sign-in El token es una credencial propia de una persona (de kubectl o de la CLI), o una de CI. Da al agente la credencial de un bot, o deja que inicie sesión en kubelatch para que tú lo autorices.
401 invalid token: this agent session expired La sesión que autorizaste para el agente llegó al final de la duración que elegiste. Vuelve a conectar el agente: inicia sesión y lo autorizas de nuevo.
401 this agent session was revoked En el error de una herramienta: un admin cortó la sesión del agente mientras se servía su petición. Habla con un admin; el agente necesita una credencial nueva.
401 this agent session expired En el error de una herramienta: la sesión del agente caducó mientras se servía su petición. Vuelve a conectar el agente.
401 this credential belongs to another agent session En el error de una herramienta: kubelatch recibió el token de un agente junto con una sesión que no es la suya, y se negó a servirlo. Apunta a un fallo de kubelatch, no a algo que hiciera el agente. Notifícalo, con el id de auditoría.
403 this agent session has no active permissions on cluster <id> En el error de una herramienta: el agente actúa en tu nombre, y ninguno de los permisos que le diste en ese cluster está vigente: tu propio permiso del que salió se revocó o caducó, o es un rol personalizado que el cluster aún no puede aplicar. Tus demás permisos nunca cuentan para el agente. El mensaje termina con kubelatch: this session has no permissions here yet; request_access asks <login> for one. Deja que el agente te lo pida con request_access, o vuelve a conectarlo incluyendo el permiso.
403 cross-origin requests are not accepted La petición llevaba una cabecera Origin distinta del origen de la URL base de kubelatch: un cliente MCP dentro de una página web, que kubelatch no soporta. Usa un cliente que se ejecute fuera del navegador.
413 request body exceeds 1048576 bytes El mensaje JSON-RPC pasa de 1 MiB. Envía un mensaje más pequeño; con apply, un objeto por llamada.
429 too many requests for this credential Más de KUBELATCH_MCP_RATE_LIMIT peticiones en el minuto actual, para esta credencial o, en un agente delegado, para esta sesión. Espera al minuto siguiente; un admin puede subir el límite.
500 kubelatch cannot query its database Postgres no responde. El proxy responde 503 en este caso; /mcp responde 500 porque la comprobación del token fija ese código. Un admin revisa Postgres.

El rechazo propio de una herramienta lleva un código, además de su texto (Resultados). Estos mensajes van al agente, en inglés:

Código Mensaje Qué significa
agent.approval_pending this write waits for a person's approval at {url} (your client may open it for you). Call the tool again right away with the same arguments and approval_id {id}: the call waits for the decision; repeat it while it answers approval_pending. It expires at {expires_at} No es un fallo: la escritura queda retenida para que decida una persona.
agent.approval_denied a person denied this write: do not try it another way Quien decide dijo que no.
agent.approval_expired the approval expired: call the tool again without approval_id to ask for a new one Nadie decidió en 15 minutos, o la escritura aprobada no se ejecutó en los 15 siguientes.
agent.approval_executed this approval already ran: read the object to see the result La aprobación ya se ejecutó, por ejemplo cuando un cliente se reconectó justo cuando la persona aprobó y una llamada anterior ejecutó la escritura.
agent.approval_mismatch approval_id does not match this call: use the same arguments as the call that asked for it La segunda llamada pide algo distinto de lo que se aprobó.
agent.too_many_pending there are already {max} approvals waiting for a decision: wait until they are decided or expire La cuenta tiene 20 solicitudes esperando.
agent.access_bad_minutes minutes must be a whole number from 1 to {max} request_access con minutes fuera de 1 a 480.
agent.access_reason reason is required, at most {max} characters request_access sin motivo, o con uno de más de 500 caracteres.
agent.batch_shape a batch approves writes of one shape: the same agent, cluster, tool, resource and namespace Una aprobación en bloque que mezcla formas o lleva una solicitud de acceso. params.index nombra la primera entrada que rompe la regla; no se decide nada.
agent.batch_size a batch holds between 1 and {max} requests Una decisión en bloque sin ids, o con más de 20.
agent.access_beyond_ceiling the agent can ask only for a role you hold on that cluster and namespace, and never for cluster-admin Un agente delegado pidió más de lo que tiene su persona allí.
agent.role_not_requestable an agent cannot ask for the role {role}: kubelatch does not know what its groups allow, so a person has to grant it request_access con un rol nativo.

Estados que solo verás en la auditoría

Estado Error Qué significa
101 Una conexión con upgrade (exec, attach, port-forward, cp). La fila se completa al cerrarse.
101 stream cut: the credential is no longer valid Un stream abierto que kubelatch cortó al revocar, caducar, deshabilitar o cambiar permisos.
499 client disconnected El cliente colgó antes de recibir la respuesta.
cualquiera kubelatch restarting El stream se cortó porque la réplica se apagaba.
403 identity.missing_fact: …, identity.bad_username: … La plantilla de identidad del cluster no pudo nombrar a la persona; el resto es el mensaje del proxy (Errores del proxy). «Entró como» queda vacío en la fila.

Errores del login con GitHub

Cuando el login con GitHub falla, kubelatch redirige a /login?error=<código> (o a /account?error=<código> si vinculabas desde «Mi cuenta»), y la página muestra el mensaje de la tabla. Cada código tiene un ancla #github-<código>.

Código Cuándo ocurre Mensaje en la interfaz
state Falta la cookie de estado, caducó (10 min), no coincide, o al vincular desde «Mi cuenta» la sesión del navegador no es la de quien empezó. La sesión de inicio con GitHub ha caducado o no es válida. Vuelve a intentarlo.
denied La persona canceló la autorización en GitHub. Has cancelado el acceso en GitHub.
github GitHub devolvió otro error, falló el canje del código, la consulta de identidad o de pertenencia, o la de los ajustes de 2FA de la organización. GitHub no ha respondido como se esperaba. Vuelve a intentarlo en un momento.
not_member La cuenta de GitHub no es miembro activo de la organización (o su invitación está pendiente). Tu cuenta de GitHub no es miembro activo de la organización.
no_2fa La organización no exige doble factor y GITHUB_REQUIRE_ORG_2FA es true. La organización de GitHub no exige doble factor; un administrador de la organización debe activarlo antes de que kubelatch acepte accesos con GitHub.
unknown_account Esa cuenta de GitHub no está vinculada a ninguna cuenta de kubelatch, o se desvinculó durante el login. Esa cuenta de GitHub no está vinculada a ninguna cuenta de kubelatch. Pide a un administrador un enlace de vinculación.
disabled La cuenta de kubelatch está deshabilitada. Tu cuenta está deshabilitada.
link_gone El enlace de invitación o vinculación caducó, ya se usó o se revocó. El enlace ha caducado o ya se ha usado; pide uno nuevo a un administrador.
github_taken Esa cuenta de GitHub ya está vinculada a otra cuenta de kubelatch. Esa cuenta de GitHub ya está vinculada a otra cuenta de kubelatch.
already_linked Desde «Mi cuenta»: tu cuenta ya está vinculada a otra cuenta de GitHub. Tu cuenta de kubelatch ya está vinculada a otra cuenta de GitHub. Pide a un administrador que la desvincule primero.
rate_limited Demasiados intentos de login desde la misma IP (10 por minuto, compartidos con el login con contraseña). Demasiados intentos desde esta dirección. Espera un minuto y vuelve a intentarlo.
server Error interno de kubelatch al completar el acceso. Error interno al completar el acceso con GitHub. Vuelve a intentarlo.

Un código desconocido muestra «No se pudo entrar con GitHub.». Casi todos los fallos dejan un login.failure con el código en el registro del plano de control; los de state por cookie ausente, caducada o de otra sesión, y los de server, solo quedan en el log. Cómo resolver cada caso está en Si algo falla y en Solución de problemas.

Errores del login con OIDC

Cuando el acceso con el proveedor OIDC falla, kubelatch redirige a /login?error=<código>&via=oidc (o a /account?error=<código>&via=oidc si vinculabas desde «Mi cuenta»), y la página muestra el mensaje de la tabla: via=oidc distingue estos códigos de los de GitHub con el mismo nombre. {name} es el nombre del proveedor, OIDC_DISPLAY_NAME. Cada código tiene un ancla #oidc-<código>. Un enrolamiento con tu identidad vuelve en cambio a /admin/clusters/<id>?error=<código>&via=oidc#enrollment, con estos códigos y dos propios: identity_mismatch (entraste con una identidad distinta de la vinculada a tu cuenta) e identity_expired (el enrolamiento caducó, o lo sustituyó otro, antes de que volvieras); la página del cluster los explica (Solución de problemas).

Código Cuándo ocurre Mensaje en la interfaz
rate_limited Demasiados intentos de login desde la misma IP (10 por minuto, compartidos con el login con contraseña y con GitHub). Demasiados intentos desde esta dirección. Espera un minuto y vuelve a intentarlo.
state Falta la cookie de estado, caducó (10 min) o no coincide, o al vincular desde «Mi cuenta» la sesión del navegador no es la de quien empezó. La sesión de inicio con {name} ha caducado o no es válida. Vuelve a intentarlo.
denied La persona canceló en el proveedor (error=access_denied). Has cancelado el acceso en {name}.
oidc El proveedor devolvió otro error, el callback no trae código o el endpoint de tokens rechazó el canje. El evento login.failure lleva el error del proveedor en idp_error. {name} no ha respondido como se esperaba. Vuelve a intentarlo en un momento.
provider_unavailable kubelatch no pudo contactar con el proveedor: su documento de descubrimiento, su endpoint de tokens, sus claves o userinfo (un error de red o un 5xx). También cuando un acceso empieza y no se puede leer el documento de descubrimiento; ese no deja evento. kubelatch no puede contactar con {name} ahora mismo. Vuelve a intentarlo en unos minutos; si sigue igual, avisa a un administrador.
token El id_token no pasó la verificación (algoritmo, firma, clave desconocida, iss, aud, azp, exp, iat, nbf, nonce, tamaño) o le falta el claim de OIDC_SUBJECT_CLAIM. kubelatch no ha podido verificar la respuesta de {name}. Vuelve a intentarlo; si sigue igual, avisa a un administrador.
no_email Ni el token ni una respuesta de userinfo que le corresponda traen una dirección de correo. {name} no ha compartido tu dirección de correo con kubelatch. Pide a un administrador que revise la configuración.
email_unverified El claim de OIDC_EMAIL_VERIFIED_CLAIM no es true. {name} no garantiza tu dirección de correo, así que kubelatch no puede emparejarla con una cuenta.
domain_not_allowed El dominio del correo no está en OIDC_ALLOWED_DOMAINS, o el claim hd de Google falta, no está permitido o no es el dominio del correo. Esa cuenta de {name} no es de un dominio que este kubelatch acepte. ¿Has elegido una cuenta personal?
unknown_account OIDC_AUTOLINK no dejó vincular la cuenta que tiene ese correo, o la identidad se desvinculó durante el acceso. Cuando ninguna cuenta tiene el correo, el callback lleva a /join (Acceso por dominio y solicitudes de alta). Ninguna cuenta de kubelatch tiene la dirección de correo de esa cuenta de {name}.
ambiguous_account Dos o más cuentas habilitadas tienen ese correo; el evento las lista en candidates. Hay más de una cuenta de kubelatch con tu dirección de correo. Pide a un administrador que lo resuelva.
disabled La cuenta está deshabilitada, o lo están las únicas cuentas con ese correo. Tu cuenta está deshabilitada.
identity_mismatch La cuenta encontrada por el correo está vinculada a otra identidad de este proveedor. Tu cuenta de kubelatch está vinculada a otra identidad de {name}. Pide a un administrador que la desvincule.
oidc_taken Esa identidad ya está vinculada a otra cuenta de kubelatch. Esa cuenta de {name} ya está vinculada a otra cuenta de kubelatch.
already_linked Desde «Mi cuenta»: tu cuenta ya tiene otra identidad de este proveedor. Tu cuenta de kubelatch ya está vinculada a otra identidad de {name}. Pide a un administrador que la desvincule primero.
link_gone El enlace de invitación o de restablecimiento ya se usó, se revocó o caducó, o su cuenta se deshabilitó. El enlace ha caducado o ya se ha usado; pide uno nuevo a un administrador.
server Error interno de kubelatch al completar el acceso. Error interno al completar el acceso con {name}. Vuelve a intentarlo.

Un código desconocido muestra «No se pudo entrar con {name}.». Con unknown_account, la página añade «Para tener cuenta, pídela a {contact}.» cuando KUBELATCH_ACCESS_CONTACT tiene valor; con unknown_account y domain_not_allowed, ofrece «Probar con otra cuenta», que abre el selector de cuentas del proveedor. Cada fallo deja un login.failure con via: oidc y el código en reason en el registro del plano de control, salvo los de state por cookie ausente, caducada o de otra sesión, los de server y un acceso que no pudo empezar (provider_unavailable antes de llegar al proveedor), que no dejan evento. Cómo resolver cada caso está en Cuando un acceso falla y en Solución de problemas.

Errores de la API

Bajo /api/ y /v1/, los errores son JSON con el texto en inglés, un código estable y sus parámetros:

{"error": "namespace kube-system is protected: it takes no permissions of any role", "code": "grant.protected_namespace", "params": {"namespace": "kube-system"}}

error es para cualquier cliente y siempre está en inglés; la interfaz traduce code con params y, si no conoce el código, muestra error. Los códigos son estables: pueden aparecer nuevos, pero los que existen no cambian de significado. La tabla cita cada código con el texto que muestra la interfaz en español.

Estado Códigos habituales (lo que muestra la interfaz) Qué significa
400 request.bad_json («cuerpo JSON no válido»); la validación que falló, por ejemplo grant.protected_namespace («el namespace kube-system está protegido: no admite permisos de ningún rol»), credential.bad_ttl («la duración (ttl) no es válida: usa por ejemplo 7d o 12h»), locale.invalid («idioma no válido: usa en o es»), enrollment.url_conflict («elige el apiserver interno del cluster o una URL de apiserver, no ambos»), enrollment.in_place_conflict («con «donde ya está» kubelatch usa la URL y la CA guardadas: no envíes otras»), enrollment.in_cluster_ca_missing («kubelatch no tiene la CA de este cluster: pégala») Petición mal formada o que no cumple la política.
401 session.missing («sesión no iniciada»); session.invalid («sesión caducada o no válida»); auth.bad_credentials («login o contraseña incorrectos») Falta la sesión, caducó o se revocó; o el login falló (el mensaje es el mismo para cualquier motivo).
403 session.admin_only («solo para administradores»); request.cross_origin («petición de otro origen rechazada»); auth.password_disabled («esta cuenta entra con un proveedor de identidad externo: no usa contraseña»); credential.forbidden («solo un administrador puede operar sobre credenciales de otros»); grant.own_only («solo puedes consultar tus propios permisos») Falta el rol, la petición viene de otro origen o la acción no está permitida a esa cuenta.
404 request.not_found («no encontrado»); enrollment.invalid («este enlace de enrolamiento no es válido o ha caducado; genera otro en Clusters»); subject.not_found («cuenta no encontrada»); cluster.not_found («cluster no encontrado»); credential.not_found («credencial no encontrada o ya revocada»); grant.not_found («permiso no encontrado o ya revocado»); link.invalid («enlace no válido»); github.not_configured («el acceso con GitHub no está configurado»); oidc.disabled («el acceso con OIDC no está configurado») El recurso no existe (o no es tuyo).
405 request.method_not_allowed («método no permitido») Ruta conocida, método no admitido. La cabecera Allow dice cuáles valen.
409 grant.exists («ese permiso ya existe»); subject.login_taken («ese login ya existe (los logins no se reutilizan)»); subject.last_admin («no se puede quitar ni deshabilitar al último administrador activo»); credential.no_grants («sin permisos activos: no hay ningún cluster al que dar acceso»); cluster.reconcile_busy («ya hay una reconciliación de este cluster en curso»); cluster.not_ready («el cluster no tiene tokens todavía: ejecuta su comando de enrolamiento»); cluster.sealed («no se pudieron descifrar los tokens del cluster (¿cambió KUBELATCH_ENCRYPTION_KEY?): rota los tokens del cluster»); account.disabled («la cuenta está deshabilitada»); oidc.already_linked («esta cuenta ya está vinculada al proveedor de identidad; un administrador puede desvincularla»); enrollment.in_progress («hay un enrolamiento con la identidad de una persona administradora en marcha en este cluster; espera a que termine»); enrollment.in_place_unavailable («este cluster aún no tiene dirección ni CA guardadas: elige dónde está»); enrollment.in_place_changed («la dirección de este cluster cambió después de que la página la enseñara: comprueba dónde está y vuelve a intentarlo»); enrollment.identity_unlinked («tu cuenta no está vinculada al proveedor de identidad: vincúlala en Mi cuenta, o usa el script») Conflicto con el estado actual: ya existe, o el cluster o la cuenta no están en un estado que permita la acción.
410 link.gone («el enlace ha caducado o ya se ha usado; pide uno nuevo a un administrador») Enlace de invitación o vinculación gastado, caducado o revocado.
413 request.body_too_large («cuerpo demasiado grande: 64 KiB como máximo») El cuerpo pasa del límite de su ruta, que params.limit da en KiB: 64, 512 para POST /api/grants/batch, 1024 para el webhook de GitHub.
429 auth.too_many_attempts («demasiados intentos») Cuenta bloqueada 15 minutos tras 5 fallos, o límite de 10 intentos por minuto e IP.
500 internal («error interno») Fallo inesperado; el detalle está en el log, en la línea request failed cuyo request_id es el X-Request-Id de la respuesta.
502 cluster.unreachable (un resumen del fallo del cluster); cluster.reconcile_failed («la reconciliación falló: la página del cluster enumera sus problemas ({count})») Listar los namespaces de un cluster, conceder un permiso o reconciliar necesitaba hablar con el cluster y no pudo. Tras una reconciliación fallida, abre el cluster: su página enumera cada problema.
503 ci.not_configured («el canje de CI no está configurado»); reconciler.unavailable («el reconciliador no está disponible»); oidc.unavailable («no se puede contactar con el proveedor de identidad ahora mismo: vuelve a intentarlo en un momento») Una pieza interna no está disponible.

Roles

Crear o editar un rol personalizado (POST y PUT /api/roles) responde 422 con la primera regla que incumple el rol; el constructor las muestra todas, junto a su capacidad o su regla. Qué significa cada regla y por qué existe está en Roles.

Estado code («texto en la interfaz») Qué hacer
422 role.bad_id («el identificador lleva de 2 a 39 letras minúsculas, cifras o guiones, empieza por una letra y acaba en letra o cifra») Cambia el «Identificador».
422 role.id_reserved («viewer es el nombre de un rol de sistema») Elige otro identificador: los nombres de los seis roles de sistema están reservados.
422 role.bad_name («el nombre es obligatorio y admite como máximo 80 caracteres») Dale al rol un nombre de hasta 80 caracteres.
422 role.description_too_long («la descripción admite como máximo 500 caracteres») Acorta la descripción.
422 role.control_chars («no se admiten caracteres de control ni de formato») Quítalos del nombre, la descripción o los nombres de objeto; la descripción es de una línea.
422 role.empty («el rol no concede nada: activa una capacidad o añade una regla») Activa una capacidad o añade una regla avanzada.
422 role.unknown_module («capacidad desconocida: pods.shell»); role.duplicate_module («la capacidad pods.logs está repetida») Usa los ids del catálogo, una vez cada uno (GET /api/role-modules).
422 role.module_needs_cluster_scope («la capacidad nodes.read necesita un rol que se pueda conceder a todo el cluster») Elige «Namespaces y todo el cluster» en «Dónde se aplica», o desactiva la capacidad.
422 role.module_not_cluster_scope («la capacidad secrets.read no está permitida en un rol que se puede conceder a todo el cluster») Desactiva la capacidad, o elige «Namespaces» en «Dónde se aplica».
422 role.cluster_scope_read_only («un rol que se puede conceder a todo el cluster es de solo lectura: el verbo patch no está permitido»); role.cluster_scope_resource («un rol que se puede conceder a todo el cluster no puede nombrar secrets») Limita un rol así a get, list y watch, sin secrets y sin más subrecursos que status, scale y pods/log.
422 role.too_many_rules («un rol admite como máximo 50 reglas avanzadas»); role.too_many_names («una regla admite como máximo 20 nombres de objeto») Hasta 50 reglas por rol y 20 nombres por regla. Divide el rol, o usa una capacidad.
422 role.rule_incomplete («una regla necesita al menos un grupo de API, un recurso y un verbo») Rellena «Recursos» y «Verbos»; un «Grupo de la API» vacío es el grupo del núcleo, que el constructor ofrece como «Grupo core».
422 role.wildcard («el comodín * no está permitido») Nombra los grupos, los recursos y los verbos uno a uno.
422 role.unknown_verb («verbo desconocido: approve»); role.forbidden_verb («el verbo escalate no está permitido nunca») Usa solo get, list, watch, create, update, patch, delete y deletecollection.
422 role.forbidden_write («un rol no puede escribir en el grupo de API rbac.authorization.k8s.io») Ningún rol escribe RBAC ni la configuración de admisión.
422 role.forbidden_resource («el recurso serviceaccounts/token no está permitido nunca») serviceaccounts/token, nodes/proxy, signers, los subrecursos approval y status de certificatesigningrequests, y escribir namespaces se rechazan con cualquier verbo.
422 role.bad_rule_name («"Apps" no es un nombre válido») Un grupo, un recurso o un nombre de objeto tiene un carácter que Kubernetes no admite.
422 role.names_verb («los nombres de objeto no pueden limitar el verbo list: solo get, update, patch y delete») Quita el verbo de la regla con nombres, o ponlo en una regla sin nombres.
422 role.no_clusters («un rol limitado a clusters necesita al menos uno»); role.bad_cluster_id («un identificador de cluster tiene de 1 a 63 letras minúsculas, dígitos o guiones y no empieza por guion»); role.duplicate_cluster («el cluster prod aparece dos veces»); role.too_many_clusters («un rol puede limitarse como mucho a 100 clusters») Corrige «Solo algunos…»: un cluster como mínimo, 100 como máximo, cada uno una vez.
422 role.too_many_roles («puede haber como mucho 200 roles personalizados») La instancia tiene 200 roles personalizados. Elimina uno que ya no uses.
422 role.native_shape («un rol nativo nombra entre 1 y 20 grupos del cluster y nada más: ni capacidades ni reglas, y se concede a todo el cluster; el nombre de un grupo tiene de 1 a 253 caracteres, sin espacios ni caracteres de control») Un rol nativo con capacidades, reglas o ámbito de namespace, sin grupos o con uno mal formado; o un rol personalizado con grupos.
422 role.native_system_group («el grupo system:masters es de los que el apiserver de Kubernetes trata como propios: un rol nativo no puede nombrar grupos que empiecen por system:»); role.native_managed_group («el grupo kubelatch:cluster:viewer es de kubelatch: un rol nativo no puede nombrar grupos que empiecen por kubelatch:») Quita el grupo: esos nombres nunca son de un rol nativo.
422 role.native_too_many_groups («un rol nativo nombra 20 grupos como máximo»); role.native_duplicate_group («el grupo oidc:developers está repetido») Hasta 20 grupos, cada uno una vez. Divide el rol si necesita más.
422 role.too_many_native_roles («puede haber como mucho 200 roles nativos») La instancia tiene 200 roles nativos, que se cuentan aparte de los personalizados. Elimina uno que ya no uses.
409 role.kind_immutable («un rol no puede pasar de personalizado a nativo ni al revés: crea uno nuevo») Un PUT con otro kind. Crea un rol nuevo.
409 role.exists («ya existe o existió un rol con ese identificador») Los identificadores no se reutilizan nunca, tampoco el de un rol eliminado. Elige otro.
409 role.stale_revision («alguien ha cambiado este rol: recárgalo y vuelve a intentarlo») Vuelve a leer el rol y repite la edición sobre su revision actual; en el constructor, «Cargar la última versión».
409 role.cluster_scope_in_use («el rol tiene 2 permisos activos sobre clusters enteros: revócalos antes de que deje de poder concederse a todo un cluster») Revoca antes los permisos del rol con ámbito *.
409 role.cluster_in_use («el rol tiene 2 permisos activos en el cluster prod: revócalos antes de quitar el cluster») Revoca antes los permisos del rol en ese cluster.
409 role.psa_in_use («el rol está concedido en 3 namespaces: no puede empezar a exigir Pod Security hasta que se revoquen esos permisos») Revoca esos permisos, guarda, y vuelve a concederlos: conceder comprueba la etiqueta de Pod Security de cada namespace.
409 role.in_use («el rol tiene 4 permisos activos: revócalos, o elimínalo revocándolos») Revócalos, o elimínalo con ?revoke_grants=true («Revocar todos y eliminar»).
400 role.system («los roles de sistema no se pueden cambiar ni eliminar») Duplica el rol de sistema y cambia la copia.
400 query.bad_revoke_grants («revoke_grants debe ser true o false») Usa ?revoke_grants=true o false.
404 role.not_found («rol no encontrado») Ningún rol tiene ese identificador, o se eliminó.

Los 409 cuentan todos los permisos activos, también los de cuentas deshabilitadas, mientras que el uso de un rol cuenta solo los de cuentas habilitadas. Editar un rol nativo que es permiso de grupo lee el cluster de ese permiso: añadir un grupo al que el cluster da acceso privilegiado responde 422 group.privileged (Grupos), y un cluster que no se puede leer, 502 cluster.unreachable.

Conceder un rol (POST /api/grants) añade estos a los códigos grant.* que ya había:

Estado code («texto en la interfaz») Qué hacer
422 grant.unknown_role («rol argo-reader desconocido») Ningún rol tiene ese identificador, o se eliminó. Un nombre que no puede ser identificador de rol sigue dando 400 grant.unknown_tier.
422 grant.role_not_on_cluster («el rol argo-reader no se puede conceder en el cluster staging») El rol está limitado a otros clusters: concédelo en uno de ellos, o edita «Dónde se aplica».
422 grant.role_namespace_only («el rol argo-reader solo se concede en un namespace: no se puede conceder a todo un cluster») Concédelo en un namespace, o haz que se pueda conceder a todo el cluster (de solo lectura).
409 grant.cluster_bootstrap_v1 («el cluster prod tiene el bootstrap anterior: vuelve a aplicar su manifiesto de bootstrap antes de conceder ahí roles personalizados») Actualiza el bootstrap de ese cluster.
400 grant.psa_required («el rol deployer exige que el namespace apps tenga la etiqueta pod-security.kubernetes.io/enforce=baseline o restricted (tiene "privileged")») Etiqueta el namespace con pod-security.kubernetes.io/enforce=baseline o restricted. Vale para los roles de sistema que lo exigen y para los personalizados que lo exigen (Riesgo y Pod Security).
422 un código role.* El rol se guardó antes de una regla que ahora incumple; edítalo en «Roles».
422 grant.role_cluster_only («el rol oidc-devs solo se concede a todo el cluster: su alcance lo deciden los bindings del propio cluster») Un rol nativo con ámbito de namespace: concédelo con ámbito *.
422 grant.privileged_ttl («este cluster da a oidc:ops acceso privilegiado: crea cargas en todos los namespaces, a través de ops-edit (edit); el permiso necesita una caducidad de 8 h como máximo») Un nombre que da el permiso tiene acceso privilegiado allí: un grupo del rol, el nombre que el cluster da a la persona o el grupo de kubelatch para el rol en un namespace privilegiado. Pon al permiso una caducidad de 8 horas como máximo. params lleva name, capability, binding, role y namespace de su primera razón.
409 grant.identity_collision («este cluster llamaría oidc:ana@acme.com a esta cuenta, como ya llama a ana: cambia antes la plantilla de identidad del cluster o una de las cuentas») La plantilla de identidad del cluster da el mismo nombre a dos cuentas.
502 cluster.unreachable Un rol nativo, un rol que puede ser privilegiado o un cluster con una plantilla de identidad distinta de la de por defecto lee el RBAC del cluster al conceder; si el cluster no se puede leer, el permiso se rechaza.

Grupos

Las rutas /api/groups (y POST /api/grants/batch) responden con estos códigos. Una entrada fallida de un lote lleva su posición en params.index, sea cual sea su código, incluidos los grant.* de un permiso.

Añadir miembros (también pasarlos desde otro grupo), o devolver la vida a una pertenencia caducada, comprueba antes cada permiso activo del grupo como se comprobaría concederlo directamente. Si uno ya no pasa, por ejemplo porque su namespace perdió la etiqueta de PSA, la llamada responde con el código grant.* de esa comprobación, params.group_grant_id con el permiso del grupo y, al añadir o pasar, params.index 0. Revoca ese permiso del grupo o arregla su namespace, y vuelve a intentarlo. Cuando kubelatch no puede preguntar al cluster de un permiso (su API server no responde, o el cluster no tiene tokens que kubelatch pueda usar), la llamada responde 502 group.cluster_unreachable, con params.group (el nombre del grupo), params.group_id, params.cluster y params.group_grant_id; aprobar una solicitud de alta en el grupo responde lo mismo.

Estado code («texto en la interfaz») Qué hacer
400 group.bad_id («el id debe tener de 1 a 63 letras minúsculas, dígitos o guiones, y empezar por letra o dígito») Elige otro id.
400 group.bad_name («el nombre es obligatorio y no puede superar los 80 caracteres») Escribe un nombre más corto.
400 group.description_too_long («la descripción no puede superar los 200 caracteres») Acórtala.
400 group.control_chars («nombres, descripciones y notas no admiten caracteres de control») Quítalos.
400 group.expiry_past («la caducidad debe ser futura») Elige una fecha posterior.
400 group.note_too_long («la nota no puede superar los 500 caracteres») Acórtala.
400 group.cluster_admin («cluster-admin es personal: no se concede a un grupo») Concede cluster-admin a una persona.
422 group.privileged («el cluster prod da a oidc:platform-admins acceso privilegiado: tiene todos los permisos en todo el cluster, a través de platform-admins (cluster-admin); un permiso de grupo no puede darlo; concédelo persona a persona, con una caducidad de 8 h como máximo») Un rol nativo cuyo grupo recibe acceso privilegiado del cluster, o un rol que escribe kubelatch en un namespace privilegiado, como permiso de grupo o añadido a un rol nativo que lo es. Concédelo a cada persona con caducidad.
400 group.batch_size («un lote admite entre 1 y 100 entradas») Divide la petición; los lotes de permisos admiten hasta 50.
400 grant.batch_size («un lote admite entre 1 y 200 permisos») Divide la petición.
400 batch.size («un lote admite entre 1 y 500 elementos») Manda al menos un id, y divide una selección mayor en peticiones de 500 como máximo.
400 batch.duplicate («el mismo elemento está dos veces en el lote») params.index y params.id nombran la segunda aparición: manda cada id una vez.
400 batch.reason_too_long («el motivo no puede pasar de 500 caracteres») Acorta el motivo.
400 group.move_choice («elige la caducidad de las nuevas pertenencias o conserva la de cada una») Al pasar miembros a otro grupo: manda expires_at (null para ninguna) o "keep_expiry": true, no los dos.
400 group.move_same («los miembros ya están en ese grupo: elige otro») Al pasar miembros a otro grupo: to_group_id es el grupo que dejan. Elige otro.
400 query.bad_group («el filtro de grupo no es un id de grupo válido») GET /api/grants?group= recibe el id de un grupo.
404 group.not_found («grupo no encontrado») El grupo no existe.
404 group.member_not_found («miembro no encontrado o ya retirado») Recarga el grupo.
404 group.grant_not_found («permiso del grupo no encontrado o ya revocado») Recarga el grupo.
409 group.exists («ese id de grupo ya existe (los ids no se reutilizan)») Elige otro id.
409 group.member_exists («esa cuenta ya es miembro») No hay nada que hacer.
409 group.subject_disabled («una cuenta deshabilitada no puede entrar en un grupo») Habilita antes la cuenta.
409 group.grant_exists («el grupo ya tiene ese permiso») No hay nada que hacer.
502 group.cluster_unreachable («Platform team tiene permisos en prod y no se puede alcanzar su API server: arregla el cluster o quita ese permiso del grupo») Al añadir miembros, devolver la vida a una pertenencia o aprobar una solicitud de alta en el grupo. Arregla el cluster (Clusters) o revoca los permisos del grupo en él, y vuelve a intentarlo.
409 grant.derived («este permiso viene del grupo pegaso: quita al miembro o revoca el permiso del grupo allí») DELETE /api/grants/{id} sobre un permiso derivado; params.group_id nombra el grupo. Quita al miembro o revoca el permiso del grupo en el propio grupo.

Ampliar permisos

PATCH /api/grants/{id} y POST /api/grants/extend comprueban la caducidad nueva como al conceder, con los códigos grant.* de arriba, y responden también estos. En un lote, el permiso que falla lleva params.index y params.id. POST /api/groups/{id}/members/extend y POST /api/groups/{id}/grants/extend de un grupo responden también batch.extend_choice y batch.no_expiry, además de los códigos de su PATCH individual.

Estado code («texto en la interfaz») Qué hacer
400 batch.extend_choice («elige una: un tiempo que sumar, una fecha o nunca») Manda exactamente uno de extend_by_seconds (más de 0), expires_at y "never_expires": true.
409 batch.no_expiry («no tiene fecha de fin que ampliar: elige una fecha») No se puede sumar tiempo a un permiso sin fecha de fin: pon una misma fecha a todos, o déjalo fuera.
409 grant.expired («este permiso ha caducado: concédelo de nuevo») Un permiso caducado no vuelve al ampliarlo: concédelo de nuevo.
409 grant.revoked («este permiso está revocado») Recarga la lista.
409 grant.privileged_lifetime («este permiso se creó el 2026-10-23T03:00:00Z; un nombre privilegiado admite 8 horas de vida desde entonces: revócalo y vuelve a concederlo») El permiso es cluster-admin, o da un nombre con acceso privilegiado, y sus 8 horas cuentan desde que se concedió, no desde ahora. Revócalo y vuelve a concederlo. params lleva los de grant.privileged_ttl más created_at.

La plantilla de identidad del cluster

Guardar la plantilla de identidad de un cluster (PATCH /api/clusters/{id}) y verla de antemano (GET /api/clusters/{id}/identity-preview?template=) responden con estos códigos:

Estado code («texto en la interfaz») Qué hacer
400 cluster.template_variables («la plantilla necesita exactamente una variable entre llaves: el login, el correo, el sujeto de OpenID Connect o el login de GitHub») Usa una sola variable, como oidc:{email}.
400 cluster.template_bad_literal («el texto fijo de la plantilla no puede empezar por system: ni contener espacios, caracteres de control o llaves sueltas») Cambia el texto que rodea a la variable.
400 cluster.template_reserved_prefix («el texto fijo de la plantilla no puede empezar por user: ni por bot:, los nombres que kubelatch da a sus propias cuentas; solo la plantilla por defecto empieza por user:») Elige otro prefijo, como oidc:, o vuelve a la plantilla por defecto.
400 cluster.template_too_long («la plantilla produce nombres de más de 253 caracteres») Acorta el texto fijo.
409 cluster.busy («otra operación está cambiando el cluster: inténtalo de nuevo en unos segundos») Guardar espera como mucho dos segundos al cluster; otro cambio lo tiene retenido. Inténtalo de nuevo en unos segundos.
409 cluster.template_needs_oidc («las variables del correo y del sujeto de OpenID Connect necesitan que el acceso con OpenID Connect esté configurado: sin él nadie los tiene») Configura antes el login con OIDC, o usa {login} o {github_login}.

La interfaz dice en sus vistas previas los dos rechazos de identidad del proxy con los códigos proxy.identity_missing_fact y proxy.identity_bad_username; el propio proxy los responde como en Errores del proxy.

Entornos y etiquetas

Las rutas de los entornos (/api/environments y sus vistas previas) y PUT /api/clusters/{id}/placement y su vista previa responden con estos códigos. Conceder o ampliar un permiso, también el de un grupo, responde grant.environment_max; GET /api/audit y GET /api/audit/summary responden query.bad_environment por sus filtros environment y production.

Estado code («texto en la interfaz») Qué hacer
400 environment.bad_id («el id debe tener de 1 a 63 letras minúsculas, dígitos o guiones, y empezar por una letra o un dígito») Elige otro id.
409 environment.exists («ya existe un entorno con ese id») Elige otro id, o usa el entorno que ya lo tiene.
404 environment.not_found («entorno no encontrado») El entorno de la ruta no existe, o se eliminó. PUT /api/clusters/{id}/placement lo responde como 400 por el entorno que nombra su cuerpo: vuelve a leer los entornos y elige uno que exista.
400 cluster.label_invalid («la etiqueta Equipo no es válida: las claves y los valores tienen de 1 a 63 caracteres, letras minúsculas, dígitos y guiones (los valores también puntos y guiones bajos), y empiezan y terminan por una letra o un dígito») Corrige la etiqueta cuya clave nombra params.key: en minúsculas, sin prefijo y sin espacios.
400 cluster.label_reserved («entorno está reservada y no puede ser la clave de una etiqueta: el entorno del cluster tiene su propio campo») Pon el entorno en environment y dale otra clave a la etiqueta.
400 cluster.labels_too_many («un cluster admite como máximo 20 etiquetas») Deja 20 etiquetas como mucho; params.max lleva el límite.
400 environment.ttl_invalid («una regla dura de 1 hora a 365 días») Da a la regla que nombra params.field, max_ttl_seconds o default_ttl_seconds, de 3600 a 31536000 segundos, o null para que el entorno no la tenga.
400 environment.default_over_max («la caducidad por defecto no puede ser más larga que el máximo») Pon una caducidad por defecto más corta, o una duración máxima más larga.
400 environment.auto_approve_role ({role} no se puede conceder sin aprobación) Un rol de auto_approve_roles que es cluster-admin, un rol nativo, un rol personalizado que no existe, un repetido o uno pasado el 50. params.role lo nombra. Quítalo de la lista.
403 edition.feature («esta función es de Pro: mira Edición en el menú») Poner o cambiar una regla, o conceder o ampliar un permiso sobre un conjunto, fuera de Pro. Las reglas guardadas se siguen aplicando, y quitarlas funciona en cualquier edición (Free y la clave caducada); los permisos sobre un conjunto siguen a sus conjuntos (En Free y con la clave caducada).
400 grant.environment_max («el entorno prod admite permisos de una persona de 8 h como mucho») Un permiso de una persona o de un grupo que terminaría después de ahora más el máximo del entorno de su cluster, o nunca: al conceder, al ampliar o al aprobar una solicitud de alta. params lleva environment y max, y en un lote también index (e id al ampliar). Elige una caducidad dentro del máximo. El permiso propio de un bot nunca lo recibe.
400 grant.reason_required (prod pide un motivo en cada permiso de una persona o de un grupo) El entorno del cluster exige un motivo y el permiso no lleva ninguno (note). params lleva environment, y en un lote también index. Ampliar y revocar nunca lo piden, ni tampoco el permiso de un bot.
400 grant.ticket_required (prod pide un ticket en cada permiso de una persona o de un grupo: una URL o una clave como INC-123) Lo mismo para el ticket: tiene que ser una URL https://, una clave como INC-123 o un número. params lleva environment, y en un lote también index.
400 grant.ticket_invalid (el ticket no puede llevar caracteres de control ni de formato) El ticket de un permiso o de una pertenencia a un grupo lleva un carácter de control o uno de formato invisible, como U+202E, que invierte el texto que lo sigue.
400 grant.ticket_too_long (el ticket no puede pasar de 200 caracteres) El ticket pasa de params.max caracteres.
400 grant.note_invalid (la nota no puede llevar caracteres de control ni de formato) La note de un permiso, el reason de una solicitud de acceso o la note de una decisión sobre ella lleva un carácter de control, como ESC, o uno de formato invisible, como U+202E. Los saltos de línea y los tabuladores sí se admiten.
409 cluster.busy («otra operación está cambiando el cluster: inténtalo de nuevo en unos segundos») Guardar el entorno y las etiquetas de un cluster, guardar un entorno o eliminarlo espera como mucho dos segundos a lo que cambia, y otro cambio lo tiene retenido. No se escribió nada: inténtalo de nuevo en unos segundos.
409 cluster.placement_changed («el entorno o las etiquetas del cluster han cambiado desde que se leyeron: revísalos y vuelve a intentarlo») Alguien cambió el entorno o las etiquetas del cluster después de que la página, o el base de la petición, los leyera. No se escribió nada: vuelve a leer el cluster y haz el cambio desde lo que tiene ahora.
400 query.bad_environment («el filtro de entorno debe ser el id de un entorno existente, production debe ser true y solo se puede dar uno de los dos») Envía environment=<id> de un entorno que exista o production=true, no los dos. Sin el rol de admin, cualquiera de los dos responde 403 session.admin_only.

Solicitudes de acceso

Las solicitudes que una persona hace para que le den un rol durante un tiempo responden estos códigos, además de los comunes:

Estado code (error) Qué hacer
404 access_request.not_found (la solicitud no existe) El id es desconocido, o la retención borró la solicitud.
400 access_request.not_requestable (ese rol no se puede pedir ahí) El rol no es un tier, un rol personalizado que el cluster admite ni un rol nativo de ese cluster, el ámbito no encaja con el rol, o el namespace está protegido.
400 access_request.duration (una solicitud pide entre 15 minutos y {max}) Pide una duración de 15 minutos a params.max, la más corta entre el máximo del entorno, el del rol y 30 días.
400 access_request.longer (una aprobación puede acortar una solicitud, nunca alargarla) La duración que aprueba un administrador es más larga que la pedida.
400 access_request.reason_required (una solicitud necesita un motivo: es lo que lee quien decide) Escribe un motivo de 1 a 500 caracteres.
409 access_request.pending_limit (ya tienes {max} solicitudes esperando: cancela una o espera a que se decidan) Cancela una de tus solicitudes pendientes, o espera a una decisión.
429 access_request.too_many (has presentado {max} solicitudes en la última hora: vuelve a intentarlo más tarde) Una persona presenta como mucho params.max solicitudes en una hora, canceladas incluidas. Espera a que la más antigua de ellas cumpla una hora.
409 access_request.closed (esta solicitud ya no espera una decisión) Se decidió, se canceló o caducó. Pídela otra vez si aún la necesitas.
409 access_request.no_decider (nadie más puede decidir esta solicitud: concédelo en Permisos) El único administrador es quien pide: concede el rol en Permisos.
403 access_request.not_decider (no puedes decidir esta solicitud) La persona no puede decidirla.
403 access_request.self (nadie decide su propia solicitud) La decide otro administrador.
403 access_request.admin_only (esta solicitud solo la decide un administrador) Pídeselo a un administrador.
400 access_request.batch_size (elige entre 1 y {max} solicitudes) Una decisión sobre varias solicitudes nombra de 1 a params.max solicitudes distintas: 50 para aprobar, 100 para denegar.
400 access_request.batch_kind (una solicitud de alta se aprueba de una en una) Aprueba cada solicitud de alta por separado; denegar sí se puede con varias a la vez.
400 access_request.extension_room (una prórroga puede sumar ahora como mucho {max} a este permiso) La solicitud nombra un permiso que tienes directamente, así que lo amplía. Pide params.max o menos: el nuevo final queda dentro del máximo del entorno contado desde ahora, y del máximo del rol.
409 access_request.extension_full (este permiso ya no admite más tiempo: pide uno nuevo cuando termine) A una prórroga le quedan menos de 15 minutos de margen. Vuelve a pedirlo cuando el permiso termine.
400 query.bad_view (view debe ser mine, waiting o decided) GET /api/access-requests con otro view, o con kind=access y sin view.
400 query.bad_kind (kind debe ser access o join) GET /api/access-requests con otro kind.
400 query.bad_namespace (namespace no válido) GET /api/request-options recibe en namespace el nombre de un namespace, junto con cluster.

Dueños

Nombrar y quitar a los dueños de un entorno, un cluster, un namespace o un grupo, y lo que hace un dueño sin ser administrador, responden estos códigos, además de los comunes. 403 edition.feature es la respuesta a nombrar un dueño fuera de Pro.

Estado code (error) Qué hacer
409 owner.exists (ese dueño ya está nombrado ahí) Esa persona o ese grupo ya es dueño del ámbito.
404 owner.not_found (el dueño no existe) El id es desconocido, o el dueño ya se quitó.
400 owner.not_person (un dueño es una persona habilitada o un grupo, nunca un bot) Nombra a una persona habilitada o un grupo.
400 owner.invalid_scope (los dueños se nombran en un entorno, un cluster, un namespace de un cluster o un grupo, y un grupo no puede ser dueño de sí mismo) Indica un ámbito (un entorno, un cluster, un namespace que no esté protegido o un grupo) y un dueño: una persona o un grupo distinto del ámbito.
403 owner.self (un dueño no puede darse acceso a sí mismo) Un dueño concede, amplía y añade para otros, nunca para sí ni para un grupo del que es miembro: pídeselo a un administrador o a otro dueño.
403 owner.admin_only (esto solo lo concede o lo cambia un administrador) cluster-admin, un rol nativo, un permiso que el cluster hace privilegiado y el acceso de un bot son cosa de un administrador.
403 owner.out_of_scope (esto queda fuera de lo que gestionas) El cluster, el namespace o el grupo no es tuyo.
409 owner.group_owns (este grupo es dueño de {scope}: solo un administrador cambia sus miembros) Mientras un grupo es dueño de algo, solo un administrador cambia sus miembros; params.scope dice de qué es dueño.
400 query.bad_managed (managed debe ser 1) GET /api/grants con un managed distinto de 1.
400 query.bad_owner_scope (indica uno solo de los filtros: entorno, cluster o grupo) GET /api/owners sin ninguno o con más de uno de environment, cluster y group.

Permisos sobre un conjunto

Las rutas de /api/cluster-set-grants (API HTTP) responden con estos códigos, además de los grant.* de un permiso, account.disabled y role.stale_revision. Una entrada fallida de una concesión lleva su posición en params.index. 403 edition.feature es la respuesta a conceder o ampliar fuera de Pro.

Un cluster al que un permiso sobre un conjunto no llega no es una petición fallida: el clusters[].refusal del permiso lleva el código y los params de por qué, con kind transient o rule (Cuándo decide kubelatch otra vez). Los códigos que salen ahí son los grant.* que responde conceder a mano (grant.namespace_missing, grant.psa_required, grant.role_not_on_cluster, grant.cluster_bootstrap_v1, grant.environment_max), cluster.unreachable, cluster.not_ready, cluster.sealed y estos dos.

Estado code («texto en la interfaz») Qué hacer
400 set_grant.target («un permiso sobre un conjunto es para una o varias cuentas o para un grupo») Manda subject_ids o group_id, exactamente uno.
400 set_grant.selector_invalid («el conjunto tiene que ser un entorno o una etiqueta clave: valor») params.field nombra lo que falla, kind, key o value. Un filtro recibe environment o label, no los dos.
400 set_grant.cluster_admin («cluster-admin es personal y por cluster: no se concede sobre un conjunto») Concede cluster-admin a una persona en un cluster.
409 set_grant.exists («ese permiso sobre el conjunto ya existe») No hay nada que hacer: params.index nombra la entrada repetida.
404 set_grant.not_found («no existe ese permiso sobre un conjunto») No existe, el id está mal formado o ya se revocó.
— set_grant.privileged («el cluster prod da a alice acceso privilegiado: tiene todos los permisos en todo el cluster, a través de ops-edit (edit); un permiso sobre un conjunto no puede darlo nunca») Un rechazo en un cluster, nunca un fallo de la petición. El acceso privilegiado se concede a mano, con una caducidad de 8 h como máximo. Los params llevan cluster, name, capability, namespace, binding y role.
— set_grant.pending («kubelatch aún no ha decidido este cluster: lo hará en un momento») Un rechazo que espera a que kubelatch decida el cluster, cosa que hace solo.
409 grant.set_derived («este permiso sigue al conjunto equipo: pagos: revoca el permiso sobre el conjunto o saca el cluster de él») DELETE /api/grants/{id}, PATCH /api/grants/{id}, los lotes y las rutas de permisos de un grupo sobre lo que un conjunto puso en un cluster. params.selector y params.set_grant_id nombran el conjunto: revoca o amplía el permiso sobre el conjunto, o cambia el entorno o las etiquetas del cluster.

Edición

Un alta por encima de un límite responde 422 edition.limit; instalar o quitar una clave tiene sus propios errores (Ediciones y licencia).

Estado code («texto en la interfaz») Qué hacer
422 edition.limit («la edición {edition} admite como mucho {max} {resource}: mira Edición en el menú») Se alcanzó un límite de la edición. params lleva resource (people, clusters o custom_roles), max y edition. Instala una clave Pro en «Edición», o libera una plaza deshabilitando a una persona o borrando un cluster; los roles personalizados son solo Pro.
422 edition.license_invalid («la clave de licencia no es válida: {reason}») La clave pegada en «Edición» no verifica; params lleva el reason. Pega de nuevo la clave entera del correo.
422 edition.trial_used («esta instancia ya tuvo su única prueba, hasta el {until}: la clave de pago llega cuando se cobra la suscripción, o escribe a pro@kubelatch.com») Una clave de prueba de otra suscripción distinta de la única prueba que tuvo esta instancia; params lleva until, el día en que acaba esa prueba. Una instancia tiene una sola prueba: la clave de pago de la suscripción nueva llega cuando acaban sus 30 días gratis y se cobra; para tenerla al momento, escribe a pro@kubelatch.com y se termina la prueba antes.
409 edition.license_from_env («la clave de licencia viene de KUBELATCH_LICENSE: cámbiala allí») Con KUBELATCH_LICENSE puesta, «Edición» no puede instalar ni quitar una clave. Cambia la variable y reinicia kubelatch.
409 edition.update_check_off («la comprobación de versiones está apagada en esta instancia») Se pidió «Comprobar ahora» con KUBELATCH_UPDATE_CHECK=false, o en una compilación sin versión. Activa la comprobación para usarlo.
502 edition.update_check_failed («la comprobación de versiones no obtuvo respuesta: inténtalo más tarde») El sitio de versiones, o el espejo de KUBELATCH_UPDATE_CHECK_URL, no respondió. El log del servidor dice por qué. Se conserva el último resultado.

Canje de CI

POST /v1/ci/github-actions/token usa el mismo formato {"error", "code", "params"}; el curl del workflow imprime error, en inglés:

Estado error (code) Qué hacer
401 invalid token (ci.bad_token) Cualquier problema del propio token: firma, caducidad, audiencia, emisor, reutilización. El motivo exacto está en el log y en el evento ci.exchange.failure. Comprueba que la audiencia es tu KUBELATCH_BASE_URL.
403 no trust rule matches this workflow (repository_owner_id=… repository_id=… ref=… environment=…): an administrator must create it in kubelatch (ci.no_rule) Un admin debe crear la regla de confianza con esos ids.
403 bot <bot> of trust rule "<rule>" is disabled (ci.rule_bot_disabled) Un admin rehabilita el bot.
403 bot <bot> has no active permissions on any cluster: grant it some in kubelatch (ci.bot_no_grants) Un admin concede permisos al bot.
429 too many attempts (auth.too_many_attempts) Más de 60 peticiones por minuto desde la misma IP.

Un token rechazado por la política (403) no se gasta: el workflow puede reintentar cuando el admin arregle la configuración.

Reglas de confianza y búsqueda de tokens

Crear una regla de confianza (POST /api/ci/trust-rules) y buscar una credencial por su token (POST /api/credentials/lookup) responden estos códigos, además de los comunes. Las dos rutas son para administradores.

Estado code («texto en la interfaz») Qué hacer
400 ci.repository_needs_github («nombrar un repositorio necesita la GitHub App; sin ella, da sus ids numéricos») Configura la GitHub App, o da repository_owner_id y repository_id en lugar del nombre.
404 ci.repository_not_found («GitHub no conoce ese repositorio, o la App no lo ve») Comprueba el nombre; la App debe tener acceso al repositorio.
400 ci.repository_moved («el repositorio cambió de nombre o de dueño: usa su nombre actual») Escribe el owner/repo actual del repositorio.
400 ci.github_not_installed («la GitHub App no está instalada en la organización: instálala, o da los ids numéricos del repositorio») Instala la App en la organización dueña del repositorio, o da los ids.
400 ci.bad_repository («el repositorio se escribe como propietario/repositorio») Escribe owner/repo. Una etiqueta dada junto a los ids debe nombrar esos mismos ids.
400 credential.bad_token («eso no es un token de kubelatch (empiezan por klt_)») Pega el token entero, con el klt_.
404 credential.unknown («ninguna credencial de esta instancia coincide con ese token») El token es de otra instancia, se copió mal, o su credencial se eliminó (con su cluster, por ejemplo).
429 auth.too_many_attempts («demasiados intentos») Más de 10 búsquedas por minuto desde la misma IP.

Webhook de GitHub

POST /v1/github/webhook responde 404 sin GITHUB_WEBHOOK_SECRET, 401 invalid signature (webhook.bad_signature) si el secreto no coincide, 415 si el content type no es application/json (webhook.bad_content_type), 413 con más de 1 MiB y 400 si el cuerpo no es JSON. Un member_removed del último administrador que puede entrar responde 200 pero no deshabilita a nadie: revisa el log.

Login con OIDC

Las rutas del login con OIDC (API HTTP) responden estos códigos, además de los comunes y, en POST /api/auth/oidc/link, los de los enlaces (404 link.invalid, 410 link.gone):

Estado code (error) Qué hacer
404 oidc.disabled («el acceso con OIDC no está configurado») El login con OIDC está desactivado en esta instancia: ver Login con OIDC (SSO).
409 oidc.already_linked («esta cuenta ya está vinculada al proveedor de identidad; un administrador puede desvincularla») Desde «Mi cuenta»: la cuenta ya tiene una identidad del proveedor. Un administrador la desvincula en «Usuarios».
503 oidc.unavailable («no se puede contactar con el proveedor de identidad ahora mismo: vuelve a intentarlo en un momento») kubelatch no ha podido leer el documento de descubrimiento del proveedor. Vuelve a intentarlo; si sigue igual, ver Solución de problemas.

Incorporación

Las rutas de Acceso por dominio y solicitudes de alta (API HTTP) responden estos códigos, además de los comunes y, al aprobar, los del grupo o del permiso concedidos, y 422 edition.limit:

Estado code (error) Qué hacer
401 join.no_identity («entra primero con tu proveedor de identidad y después pide unirte») La persona no tiene una cookie de unión válida, ya la gastó o una cuenta ya tiene la identidad. Vuelve a entrar con el proveedor.
409 join.pending («ya pediste unirte: un administrador aún no lo ha decidido») Su solicitud sigue pendiente: la decide un administrador en «Usuarios».
429 join.too_many («hay demasiadas personas esperando para unirse: vuelve a intentarlo más tarde o habla con un administrador») Hay 100 solicitudes pendientes: decide algunas en «Usuarios».
400 join.bad_reason («el motivo admite hasta 500 caracteres y ningún carácter de control») El motivo es demasiado largo o tiene un carácter de control.
404 join.not_found («no se encuentra la solicitud de alta») Recarga «Usuarios»: la solicitud no está, o no es una solicitud de alta.
410 join.expired («esta solicitud de alta caducó: la persona puede volver a pedirlo») La solicitud esperó 30 días, o su proveedor ya no es el configurado: la persona vuelve a pedirlo.
409 join.decided («esta solicitud de alta ya está decidida») Alguien la decidió antes, o la persona entró por otra vía.
409 join.email_taken («ya existe una cuenta con este correo o esta identidad: vincúlala desde Usuarios») Una cuenta tiene ya ese correo o esa identidad: vincula esa cuenta (Otras formas de vincular) y deniega la solicitud.
400 join.bad_access («el acceso inicial es un grupo, un permiso o ninguno, con lo que cada uno necesita») Manda group con un group_id, grant con un grant, o none solo.
400 join.bad_note («la nota admite hasta 500 caracteres y ningún carácter de control») Acorta la nota o quítale los caracteres de control.
422 signup_domain.not_allowed («acme.com no está en OIDC_ALLOWED_DOMAINS: solo un dominio permitido puede dar de alta a personas») Añade antes el dominio a OIDC_ALLOWED_DOMAINS; params.domain lo nombra.
409 signup_domain.exists («acme.com ya tiene una regla de alta») El dominio ya tiene regla: cambia su caducidad, o quítala y añade otra.
404 signup_domain.not_found («no hay ninguna regla de alta para ese dominio») Recarga «Usuarios».
409 signup_domain.group_in_use («la regla de alta de acme.com apunta a este grupo: quita la regla o apúntala a otro grupo primero») Al borrar un grupo al que apunta una regla: quita antes la regla; params.domain la nombra.
400 signup_domain.bad_ttl («la caducidad de la pertenencia va de 1 minuto a 3650 días, o ninguna») Elige entre 1 minuto y 3650 días, o sin caducidad.
400 signup_domain.bad_group («elige un grupo que ya exista o crea uno nuevo, no las dos cosas») Manda group_id o new_group, uno de los dos.
400 query.bad_request_status («status debe ser pending o decided») GET /api/access-requests admite pending o decided.

Login de la CLI de kubelatch

La CLI imprime error; las páginas de aprobación muestran el código traducido.

Estado Código (lo que muestra la interfaz) Qué significa
400 cli.pending («esperando la aprobación en el navegador») Normal mientras kubelatch login --device espera; la CLI sigue preguntando.
429 cli.slow_down («consultas demasiado seguidas: espera más entre una y otra») La CLI espera cinco segundos más entre consultas.
400, 404 cli.invalid_code («código no válido o desconocido») Un código de --device mal escrito, o un código, verificador o id que no cuadran.
410 cli.expired («esta petición de acceso ha caducado o ya se usó: vuelve a ejecutar kubelatch login») Pasaron más de 10 minutos, alguien la canceló o ya estaba aprobada.
403 cli.not_user («solo las personas con la cuenta habilitada pueden entrar en la CLI») Se deshabilitó la cuenta entre la aprobación y el canje.
403 cli.scope («un token de la CLI solo llega a tu cuenta, tus accesos, tus credenciales y tus solicitudes: para lo demás, usa la interfaz web») Se usó un token de la CLI en una ruta a la que no llega.

Agentes de IA

Las rutas bajo /api/agents/ (API HTTP) responden estos códigos, además de los comunes:

Estado Código (lo que muestra la interfaz) Qué significa
400 agent.batch_size («un lote tiene entre 1 y 20 solicitudes») POST /api/agents/requests/approve o /deny sin ids o con más de 20.
400 agent.cut_batch_size («puedes cortar de 1 a 50 sesiones a la vez») POST /api/agents/sessions/cut sin ids o con más de 50.
400 query.state («state debe ser active o ended») GET /api/agents/sessions con un state que no es active ni ended.
400 subject.not_bot («esto solo vale para bots») PATCH /api/subjects/{id} con agent_writes_need_approval en una persona: el interruptor es de un bot.
403 agent.own_only («solo puedes ver tus propias sesiones de agente y sus solicitudes») Alguien que no es admin filtró por otra cuenta.
403 agent.not_decider («no puedes decidir esta solicitud: las de un bot las decide un administrador, y las de una sesión delegada, su dueño») Puedes ver la solicitud pero no decidirla: un admin que mira la solicitud de una sesión delegada.
404 agent.session_not_found («sesión de agente no encontrada») La sesión no existe, o no es tuya.
404 agent.request_not_found («solicitud no encontrada») La solicitud no existe, o no es tuya.
409 agent.request_closed («esta solicitud ya se decidió o caducó») Alguien la decidió antes, o se acabó su tiempo.
409 agent.cut_batch («la sesión {session} ya no está activa: no se cortó ninguna») Una sesión de POST /api/agents/sessions/cut ya estaba cortada o había caducado; params.session nombra la primera y no se corta ninguna.
422 agent.batch_shape («un lote aprueba escrituras de una misma forma: el mismo agente, cluster, tool, recurso y namespace») Una aprobación en bloque que mezcla formas o lleva una solicitud de acceso.

Conectar un agente (OAuth)

Los endpoints por los que entra un cliente MCP (/oauth/register, /oauth/token, /oauth/revoke) responden errores de OAuth (RFC 6749), {"error": "<código>", "error_description": "<texto en inglés>"}, para quien desarrolla el cliente. Los de /oauth/authorize se ven en cambio en texto plano en el navegador (más abajo).

Estado error Qué significa
400 invalid_request Falta un parámetro obligatorio o está mal formado: PKCE con S256, state o scope demasiado largos, o un formulario que no es application/x-www-form-urlencoded de 16 KiB como mucho.
400 invalid_client kubelatch no conoce el client_id, o no pudo usar su documento de metadatos.
400 invalid_grant El código o el refresh token es desconocido, ha caducado, ya se usó, se emitió para otro cliente, o su sesión de agente terminó o su cuenta está deshabilitada: el cliente vuelve a iniciar sesión. Un refresh token o un código presentado por segunda vez corta además la sesión de agente a la que pertenece.
400 invalid_target El resource no es <KUBELATCH_BASE_URL>/mcp.
400 unsupported_grant_type grant_type no es ni authorization_code ni refresh_token.
400 unsupported_response_type response_type no es code.
400 invalid_redirect_uri Un registro sin URI de redirección, con más de las permitidas, o con una que no es https, http en localhost, 127.0.0.1 o [::1], ni el esquema propio de una aplicación; o que lleva fragmento; o cuyo esquema kubelatch rechaza: javascript, file y similares, y los de los navegadores (googlechrome, firefox, intent…), que abren la dirección https que envuelven. La lista está en Servidor MCP.
400 invalid_client_metadata Un registro que no es un objeto JSON de 64 KiB como mucho, o que pide un secreto de cliente, un tipo de grant distinto de authorization_code y refresh_token, o un tipo de respuesta distinto de code.
— access_denied En la dirección de vuelta: la persona denegó el agente en la página de consentimiento.
429 temporarily_unavailable Una dirección envió demasiadas peticiones (20 registros, 30 autorizaciones, 120 peticiones de token o de revocación por minuto); Retry-After dice cuándo volver a intentarlo.
503 temporarily_unavailable too many registered clients; try again later: kubelatch tiene tantos clientes como acepta (10 000, autorregistrados e identificados por URL por igual) hasta que se limpien los que no se usan. Un cliente nuevo identificado por URL lo recibe de /oauth/authorize, en texto plano.
500 server_error Algo falló dentro de kubelatch; su log tiene la causa.

Las rutas bajo /oauth/ y /.well-known/ que no existen responden 404 {"error": "not_found"}. Cuando KUBELATCH_MCP_ENABLED es false, lo hacen todas, /mcp responde 404, y también la API de consentimiento de más abajo.

GET /oauth/authorize se abre en tu navegador. Responde sus errores en texto plano en vez de mandarte a ningún sitio, ante todo estos:

Estado Mensaje Qué significa
400 invalid_client: unknown client_id, or its metadata document could not be used kubelatch no conoce el cliente, o no pudo leer o aceptar su documento de metadatos.
400 invalid_request: redirect_uri is not one the client registered La dirección a la que el cliente quiere volver no es una que registrara, o es de un tipo que kubelatch ya rechaza (el esquema de un navegador que el cliente registró antes).
429 too many requests from this address: try again in a minute Más de 30 autorizaciones por minuto desde tu dirección.

Cualquier otro problema se ve también en texto plano, <error>: <descripción> con los códigos de la tabla anterior, y no te manda a ningún sitio, sea cual sea el cliente: cualquiera puede registrar un cliente con cualquier dirección, o publicar un documento de metadatos que nombre una, así que kubelatch nunca manda un error a una dirección de la que no puede responder. Solo tu respuesta en la página de consentimiento vuelve al cliente.

La página de consentimiento, donde eliges qué puede hacer el agente, muestra estos errores:

Estado Código (lo que muestra la interfaz) Qué significa
400 oauth.nothing_delegated («elige al menos un permiso para el agente») Dejaste fuera todos los permisos.
400 oauth.bad_choice («el agente no puede recibir de tu permiso ») La elección está por encima de tu propio rol ahí, o el permiso ya no es tuyo o ya no está activo. Un agente nunca hereda cluster-admin.
400 oauth.bad_follow («follow debe ser none, viewer o same») La elección para los permisos que recibas más adelante no era ninguna de esas.
400 oauth.bad_duration («la duración debe ir de 5 minutos a ») La duración de la sesión está fuera de los límites; el máximo es KUBELATCH_AGENT_SESSION_MAX_TTL.
403 oauth.not_user («solo las personas con la cuenta activa pueden autorizar a un agente») Tu cuenta se deshabilitó entretanto.
404 oauth.authorization_not_found («no se encuentra la solicitud de autorización») El enlace está mal, u otra persona ya la respondió.
410 oauth.authorization_closed («esta solicitud de autorización ha caducado o ya se respondió: vuelve a conectar el agente») Pasaron más de 10 minutos, o ya se aprobó o se denegó.

Al aprobar una solicitud de acceso de un agente, un 409 con agent.access_beyond_ceiling («el agente solo puede pedir un rol que tú tengas en ese cluster y namespace, y nunca cluster-admin») significa que tu propio permiso en el que se apoyaba ya no está; la solicitud sigue pendiente hasta que caduque.