{"record":{"id":"25db8859e896d63a","repo":"jwtk/jjwt","slug":"unable-to-decode-input-e-getmessage","errorCode":null,"errorMessage":"Unable to decode input: ${e.getMessage()}","messagePattern":"Unable to decode input: (.+?)","errorType":"exception","errorClass":"DecodingException","httpStatus":null,"severity":"error","filePath":"api/src/main/java/io/jsonwebtoken/io/ExceptionPropagatingDecoder.java","lineNumber":57,"sourceCode":"\n    /**\n     * Decode the specified encoded data, delegating to the wrapped Decoder, wrapping any\n     * non-{@link DecodingException} as a {@code DecodingException}.\n     *\n     * @param t the encoded data\n     * @return the decoded data\n     * @throws DecodingException if there is an unexpected problem during decoding.\n     */\n    @Override\n    public R decode(T t) throws DecodingException {\n        Assert.notNull(t, \"Decode argument cannot be null.\");\n        try {\n            return decoder.decode(t);\n        } catch (DecodingException e) {\n            throw e; //propagate\n        } catch (Exception e) {\n            String msg = \"Unable to decode input: \" + e.getMessage();\n            throw new DecodingException(msg, e);\n        }\n    }\n}\n","sourceCodeStart":39,"sourceCodeEnd":61,"githubUrl":"https://github.com/jwtk/jjwt/blob/fb71496164c71442d08adec4571d9616ed5e1b8d/api/src/main/java/io/jsonwebtoken/io/ExceptionPropagatingDecoder.java#L39-L61","documentation":"ExceptionPropagatingDecoder is JJWT's wrapper that adapts any Decoder implementation into JJWT's Decoder contract. Its decode method rethrows DecodingException as-is, but if the delegate decoder throws any other checked/unchecked Exception (e.g. IOException from a custom decoder), it is wrapped in a DecodingException with 'Unable to decode input: ...'. This normalizes decoder failures for callers while keeping the original cause.","triggerScenarios":"Using a custom Decoder (e.g. via io.jsonwebtoken.io.Decoders or supplied to an Encoder/Decoder-based component) whose decode() throws a non-DecodingException — a raw IOException, RuntimeException, or third-party library exception — during any JJWT operation that decodes input (token parsing, Base64 decoding of keys, etc.).","commonSituations":"A custom Decoder reading from a stream/file that fails with IOException; a delegate decoder throwing NullPointerException on malformed input instead of DecodingException; mixing JJWT versions where a decoder returns unexpected types; byte[] vs String misuse with a decoder expecting a different input type.","solutions":["Check getCause() to find the real failure from the delegate decoder and fix that root cause","Verify the input type matches what the decoder expects (String vs byte[]) and that the data is valid for the decoder's format","If you wrote a custom Decoder, catch your internal failures and throw DecodingException from decode() so they propagate unchanged","Ensure consistent JJWT api/impl/runtime versions on the classpath to avoid mismatched decoder behavior"],"exampleFix":"// before\npublic byte[] doDecode(String s) throws IOException {\n    return Files.readAllBytes(Paths.get(s)); // raw IOException -> Unable to decode input\n}\n\n// after\npublic byte[] doDecode(String s) {\n    try {\n        return Files.readAllBytes(Paths.get(s));\n    } catch (IOException e) {\n        throw new DecodingException(\"Unable to read input\", e);\n    }\n}","handlingStrategy":"try-catch","validationCode":"// Java: check input type and nullness before handing to a decoder\nboolean isDecodableInput(Object in) {\n    if (in instanceof String s) return !s.isEmpty();\n    if (in instanceof byte[] b) return b.length > 0;\n    return false;\n}","typeGuard":"boolean isStringOrBytes(Object in) {\n    return in instanceof String || in instanceof byte[];\n}","tryCatchPattern":"try {\n    byte[] out = decoder.decode(input);\n} catch (DecodingException e) {\n    Throwable root = e.getCause();\n    // null cause = delegate threw DecodingException; non-null = wrapped unexpected failure\n}","preventionTips":["Throw DecodingException (not raw IOException/RuntimeException) from custom Decoder implementations","Confirm the input type matches the decoder contract (String vs byte[]) before decoding","Keep JJWT api/impl versions aligned to avoid cross-version decoder mismatches","Null/empty-check inputs before decode calls","Inspect getCause() whenever you see the 'Unable to decode input' wrapper"],"tags":["decoding","base64","jwt"],"backgroundTag":"invalid-argument-format","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"}