{"record":{"id":"b55aadfe263bd6c0","repo":"jwtk/jjwt","slug":"invalid-protected-header-e-getmessage","errorCode":null,"errorMessage":"Invalid protected header: ${e.getMessage()}","messagePattern":"Invalid protected header: (.+?)","errorType":"exception","errorClass":"MalformedJwtException","httpStatus":null,"severity":"error","filePath":"impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParser.java","lineNumber":389,"sourceCode":"        Assert.stateNotNull(unencodedPayload, \"internal error: unencodedPayload is null.\");\n\n        final TokenizedJwt tokenized = jwtTokenizer.tokenize(compact);\n        final CharSequence base64UrlHeader = tokenized.getProtected();\n        if (!Strings.hasText(base64UrlHeader)) {\n            String msg = \"Compact JWT strings MUST always have a Base64Url protected header per \" +\n                    \"https://tools.ietf.org/html/rfc7519#section-7.2 (steps 2-4).\";\n            throw new MalformedJwtException(msg);\n        }\n\n        // =============== Header =================\n        final byte[] headerBytes = decode(base64UrlHeader, \"protected header\");\n        Map<String, ?> m = deserialize(Streams.of(headerBytes), \"protected header\");\n        Header header;\n        try {\n            header = tokenized.createHeader(m);\n        } catch (Exception e) {\n            String msg = \"Invalid protected header: \" + e.getMessage();\n            throw new MalformedJwtException(msg, e);\n        }\n\n        // https://tools.ietf.org/html/rfc7515#section-10.7 , second-to-last bullet point, note the use of 'always':\n        //\n        //   *  Require that the \"alg\" Header Parameter be carried in the JWS\n        //      Protected Header.  (This is always the case when using the JWS\n        //      Compact Serialization and is the approach taken by CMS [RFC6211].)\n        //\n        final String alg = Strings.clean(header.getAlgorithm());\n        if (!Strings.hasText(alg)) {\n            String msg = tokenized instanceof TokenizedJwe ? MISSING_JWE_ALG_MSG : MISSING_JWS_ALG_MSG;\n            throw new MalformedJwtException(msg);\n        }\n        final boolean unsecured = Jwts.SIG.NONE.getId().equalsIgnoreCase(alg);\n\n        final CharSequence base64UrlDigest = tokenized.getDigest();\n        final boolean hasDigest = Strings.hasText(base64UrlDigest);\n        if (unsecured) {","sourceCodeStart":371,"sourceCodeEnd":407,"githubUrl":"https://github.com/jwtk/jjwt/blob/fb71496164c71442d08adec4571d9616ed5e1b8d/impl/src/main/java/io/jsonwebtoken/impl/DefaultJwtParser.java#L371-L407","documentation":"The Base64Url-decoded protected header bytes could not be turned into a Header instance — either the JSON did not deserialize into the expected structure or TokenizedJws.createHeader rejected its contents (e.g. missing/invalid required fields). parse() wraps any such exception in a MalformedJwtException with this message.","triggerScenarios":"Header JSON is structurally invalid (not an object, wrong types for fields like 'alg' not a string), or header bytes decode to garbage that fails Jackson deserialization, causing createHeader to throw.","commonSituations":"Hand-crafted or fuzzed tokens; tokens produced by buggy/other JWT implementations emitting non-JSON headers; corruption of the header segment in transit; decoding mistakes yielding non-UTF8 bytes.","solutions":["Inspect the token's first segment (base64url-decode it) to see the actual header JSON and fix the issuer that produced it","Catch MalformedJwtException around parse() and reject the token as untrusted","Ensure all token producers use standard JWT serialization (JSON object header with string 'alg')"],"exampleFix":"// before\nClaims c = Jwts.parser().verifyWith(key).build().parseSignedClaims(rawToken).getBody(); // throws\n// after\ntry {\n    Claims c = Jwts.parser().verifyWith(key).build().parseSignedClaims(rawToken).getBody();\n} catch (MalformedJwtException e) {\n    log.warn(\"Rejected malformed JWT: {}\", e.getMessage());\n    throw new UnauthorizedException();\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    return parser.parseSignedClaims(token);\n} catch (MalformedJwtException e) {\n    if (e.getMessage().startsWith(\"Invalid protected header\")) {\n        log.warn(\"JWT header not deserializable: {}\", e.getMessage());\n    }\n    throw new UnauthorizedException(e);\n}","preventionTips":["Use standard JWT libraries for token production (never hand-roll headers)","Base64url-decode the header in tests to validate issuer output","Reject tokens at ingress with a broad MalformedJwtException catch"],"tags":["jwt","malformed-header","json"],"backgroundTag":"json-parse-error","analyzedSha":"fb71496164c71442d08adec4571d9616ed5e1b8d","analyzedAt":"2026-09-09T00:33:09.982Z","contentChangedAt":"2026-09-09T00:33:09.982Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}