{"record":{"id":"e2337554d5cbe56f","repo":"spring-projects/spring-security","slug":"an-error-occurred-while-attempting-to-decode-the-j-e23375","errorCode":null,"errorMessage":"An error occurred while attempting to decode the Jwt: Malformed payload","messagePattern":"An error occurred while attempting to decode the Jwt: Malformed payload","errorType":"exception","errorClass":"BadJwtException","httpStatus":null,"severity":"error","filePath":"oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusJwtDecoder.java","lineNumber":189,"sourceCode":"\t\t\t\t\t.claims((c) -> c.putAll(claims))\n\t\t\t\t\t.build();\n\t\t\t// @formatter:on\n\t\t}\n\t\tcatch (RemoteKeySourceException ex) {\n\t\t\tthis.logger.trace(\"Failed to retrieve JWK set\", ex);\n\t\t\tif (ex.getCause() instanceof ParseException) {\n\t\t\t\tthrow new JwtException(String.format(DECODING_ERROR_MESSAGE_TEMPLATE, \"Malformed Jwk set\"), ex);\n\t\t\t}\n\t\t\tthrow new JwtException(String.format(DECODING_ERROR_MESSAGE_TEMPLATE, ex.getMessage()), ex);\n\t\t}\n\t\tcatch (JOSEException ex) {\n\t\t\tthis.logger.trace(\"Failed to process JWT\", ex);\n\t\t\tthrow new JwtException(String.format(DECODING_ERROR_MESSAGE_TEMPLATE, ex.getMessage()), ex);\n\t\t}\n\t\tcatch (Exception ex) {\n\t\t\tthis.logger.trace(\"Failed to process JWT\", ex);\n\t\t\tif (ex.getCause() instanceof ParseException) {\n\t\t\t\tthrow new BadJwtException(String.format(DECODING_ERROR_MESSAGE_TEMPLATE, \"Malformed payload\"), ex);\n\t\t\t}\n\t\t\tthrow new BadJwtException(String.format(DECODING_ERROR_MESSAGE_TEMPLATE, ex.getMessage()), ex);\n\t\t}\n\t}\n\n\tprivate Jwt validateJwt(Jwt jwt) {\n\t\tOAuth2TokenValidatorResult result = this.jwtValidator.validate(jwt);\n\t\tif (result.hasErrors()) {\n\t\t\tCollection<OAuth2Error> errors = result.getErrors();\n\t\t\tString validationErrorString = getJwtValidationExceptionMessage(errors);\n\t\t\tthrow new JwtValidationException(validationErrorString, errors);\n\t\t}\n\t\treturn jwt;\n\t}\n\n\tprivate String getJwtValidationExceptionMessage(Collection<OAuth2Error> errors) {\n\t\tfor (OAuth2Error oAuth2Error : errors) {\n\t\t\tif (StringUtils.hasLength(oAuth2Error.getDescription())) {","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/spring-projects/spring-security/blob/96852e8860138a482cb13d1479573f24ff6443c6/oauth2/oauth2-jose/src/main/java/org/springframework/security/oauth2/jwt/NimbusJwtDecoder.java#L171-L207","documentation":"NimbusJwtDecoder.createJwt's final catch-all converts a generic failure whose cause is a ParseException into a BadJwtException with the message 'An error occurred while attempting to decode the Jwt: Malformed payload'. This indicates the JWT string itself could not be parsed as a JOSE object — its compact form is not valid base64url-encoded JSON parts.","triggerScenarios":"decode(encodedJwt) is called with a string that is not a syntactically valid JWT: wrong number of dot-separated segments, segments not valid base64url, payload not valid JSON (causing Nimbus' ParseException as the cause), or whitespace/garbage passed in place of the token.","commonSituations":"Client sends 'Bearer null'/'undefined' or an empty/truncated token in the Authorization header; a Bearer token with extra characters (e.g. 'Bearer' prefix not stripped) or a token from a different format (opaque token, not JWT) is handed to the decoder; copying a token with line breaks.","solutions":["Log the raw Authorization header and inspect the token: it must be three base64url segments separated by dots.","Ensure the Bearer prefix is stripped and no whitespace/newlines are passed to decode().","Verify the client is actually configured to obtain JWTs from the IdP (an opaque/reference token will not parse).","Catch BadJwtException specifically to return 401 to the caller instead of 500."],"exampleFix":"// before\nString token = request.getHeader(\"Authorization\"); // \"Bearer eyJ...\"\nJwt jwt = this.decoder.decode(token);\n// after\nString token = request.getHeader(\"Authorization\");\nif (token != null && token.startsWith(\"Bearer \")) {\n    token = token.substring(7).trim();\n}\nJwt jwt = this.decoder.decode(token);","handlingStrategy":"validation","validationCode":"// Validate compact JWT form before calling decode\nstatic boolean isPlausibleJwt(String token) {\n    if (token == null || token.isBlank()) return false;\n    String[] parts = token.split(\"\\\\.\");\n    if (parts.length != 3) return false;\n    try {\n        Base64.getUrlDecoder().decode(parts[0]);\n        Base64.getUrlDecoder().decode(parts[1]);\n        return true;\n    } catch (IllegalArgumentException e) {\n        return false;\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    Jwt jwt = decoder.decode(token);\n} catch (BadJwtException ex) {\n    // malformed token -> always 401, never 500; do not retry\n    throw new ResponseStatusException(HttpStatus.UNAUTHORIZED, \"Invalid token format\");\n}","preventionTips":["Strip the 'Bearer ' prefix and trim whitespace before decode()","Reject empty/null Authorization headers early in a filter","Confirm the client uses the JWT flow (opaque tokens cannot be decoded by NimbusJwtDecoder)","Never copy tokens across systems with added quoting or line breaks"],"tags":["jwt","malformed-payload","bad-token","spring-security","base64"],"backgroundTag":"malformed-jwt","analyzedSha":"96852e8860138a482cb13d1479573f24ff6443c6","analyzedAt":"2026-09-10T23:25:23.477Z","contentChangedAt":"2026-09-10T23:25:23.477Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}