Mensaje de error
Invalid Compact JWS
jose (JavaScript) — JWSInvalid, code ERR_JWS_INVALID
Qué significa
jose no pudo dividir la entrada en los tres segmentos separados por puntos de la serialización compacta de JWS (header.payload.signature). La cadena que le pasas no tiene la estructura de un token firmado; no se llegó a intentar ninguna operación criptográfica. Es el equivalente en jose del error «jwt malformed» de jsonwebtoken y, como ese error, indica que el problema está antes de la biblioteca JWT: en lo que generó o transportó la cadena.
Por qué ocurre
El token se truncó o se unió a otro
frecuenteUn valor que perdió su último segmento (una columna de base de datos, una línea de registro, una copia parcial) o dos tokens concatenados en un mismo encabezado ya no tienen exactamente tres segmentos. Un prefijo «Bearer » o unas comillas JSON alrededor de un token intacto no provocan este mensaje: la cadena sigue teniendo tres segmentos, y jose da en su lugar el error «JWS Protected Header is invalid»; un salto de línea al final se tolera.
La variable no contiene un token
frecuenteundefined convertido en «undefined», una cadena vacía porque falta una cookie o un token de acceso OAuth opaco (que no es un JWT): nada de esto tiene estructura JWS. El fallo está antes de jose.
Un JWE pasado a una API de JWS
ocasionalLos tokens cifrados (JWE) tienen cinco segmentos, no tres. Si tu emisor cifra los tokens, jwtVerify/compactVerify los rechazarán aquí: el punto de entrada correcto es el descifrado (jwtDecrypt), seguido de la verificación del JWS anidado, si lo hay.
Cómo solucionarlo
- 1.
Sanear la entrada y comprobar los segmentos
Recorta los espacios, quita el esquema y comprueba el número de segmentos antes de llamar a jose: así obtienes errores precisos a nivel de aplicación en lugar de un fallo de análisis genérico.
js const token = raw.replace(/^Bearer\s+/i, "").trim(); const segments = token.split(".").length; if (segments !== 3) throw new Error(`expected JWS (3 segments), got ${segments}`); - 2.
Derivar los tokens JWE al descifrado
Si cuentas cinco segmentos, el token está cifrado. Usa jwtDecrypt con la clave privada del destinatario en lugar de jwtVerify.
js import { jwtDecrypt } from "jose"; const { payload } = await jwtDecrypt(token, privateKey); // 5-segment JWE - 3.
Rastrear dónde se construyó la cadena
Si un valor ya saneado sigue fallando, registra su longitud y sus primeros caracteres en cada salto: cliente, pasarela, almacenamiento, manejador. El primer segmento de un JWT firmado es JSON en base64url, así que los tokens reales empiezan por «eyJ» (la codificación de '{"'); el salto en el que eso deja de cumplirse es donde se produce la corrupción.
js console.log(token.length, JSON.stringify(token.slice(0, 12))); // healthy: 300+ 'eyJhbGciOiJF'