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>.
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 |
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.