{"record":{"id":"6617c20bb225d923","repo":"lcobucci/jwt","slug":"error-while-decoding-from-json","errorCode":null,"errorMessage":"Error while decoding from JSON","messagePattern":"Error while decoding from JSON","errorType":"exception","errorClass":"Lcobucci\\JWT\\Encoding\\CannotDecodeContent","httpStatus":null,"severity":"error","filePath":"src/Encoding/JoseEncoder.php","lineNumber":37,"sourceCode":" * A utilitarian class that encodes and decodes data according to JOSE specifications\n */\nfinal readonly class JoseEncoder implements Encoder, Decoder\n{\n    public function jsonEncode(mixed $data): string\n    {\n        try {\n            return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR);\n        } catch (JsonException $exception) {\n            throw CannotEncodeContent::jsonIssues($exception);\n        }\n    }\n\n    public function jsonDecode(string $json): mixed\n    {\n        try {\n            return json_decode(json: $json, associative: true, flags: JSON_THROW_ON_ERROR);\n        } catch (JsonException $exception) {\n            throw CannotDecodeContent::jsonIssues($exception);\n        }\n    }\n\n    public function base64UrlEncode(string $data): string\n    {\n        return SodiumBase64Polyfill::bin2base64(\n            $data,\n            SodiumBase64Polyfill::SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING,\n        );\n    }\n\n    public function base64UrlDecode(string $data): string\n    {\n        return SodiumBase64Polyfill::base642bin(\n            $data,\n            SodiumBase64Polyfill::SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING,\n        );\n    }","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/lcobucci/jwt/blob/375813049c24c7111bda8b6884c57b071ceb2fe7/src/Encoding/JoseEncoder.php#L19-L55","documentation":"JoseEncoder::jsonDecode wraps json_decode() with JSON_THROW_ON_ERROR; when PHP's json_decode() raises a JsonException (malformed JSON, invalid UTF-8, depth overflow), the encoder rethrows it wrapped in CannotDecodeContent::jsonIssues with the generic message 'Error while decoding from JSON'. It is thrown whenever the library must decode a JSON payload (e.g. a JWT's header or claims segment) and the input is not valid JSON.","triggerScenarios":"Calling jsonDecode() (directly or via token parsing) with a string that is not valid JSON: truncated JWT segments, base64url strings decoded to garbage, double-encoded JSON, or invalid UTF-8 bytes.","commonSituations":"Receiving a token that was truncated or corrupted in transport/cookies; decoding a payload segment without first base64url-decoding it; a client sending raw form-encoded or XML bodies to an endpoint that expects JSON; PHP json_decode failing on invalid UTF-8 from external systems.","solutions":["Inspect the raw string being passed to jsonDecode() (var_dump/log it) and validate it with json_decode($json) manually to see the exact JsonException message.","Fix the producer of the JSON: ensure the client sends valid JSON (Content-Type: application/json, no HTML error pages in the body).","For JWT workflows, verify the token is three dot-separated base64url segments and base64url-decode each segment before JSON decoding.","Catch CannotDecodeContent at the boundary and return a 400-style response instead of leaking the exception.","Check that the data wasn't mangled by transport (trailing whitespace is fine, but NUL bytes or charset conversion damage is not)."],"exampleFix":"// before\n$claims = $encoder->jsonDecode($request->getBody()); // throws CannotDecodeContent on bad JSON\n\n// after\n$raw = $request->getBody();\nif (json_validate($raw)) {\n    $claims = $encoder->jsonDecode($raw);\n} else {\n    throw new BadRequestException('Request body is not valid JSON');\n}","handlingStrategy":"try-catch","validationCode":"// PHP 8.3+\nif (!function_exists('json_validate') ? json_decode($raw) === null && json_last_error() !== JSON_ERROR_NONE : !json_validate($raw)) {\n    throw new InvalidArgumentException('Input is not valid JSON');\n}","typeGuard":"function isJsonString(?string $raw): bool\n{\n    if ($raw === null || $raw === '') {\n        return false;\n    }\n    json_decode($raw);\n    return json_last_error() === JSON_ERROR_NONE;\n}","tryCatchPattern":"try {\n    $data = $encoder->jsonDecode($raw);\n} catch (CannotDecodeContent $e) {\n    // $e->getPrevious() is the JsonException with the exact offset/reason\n    error_log('JSON decode failed: ' . $e->getPrevious()?->getMessage());\n    throw new BadRequestException('Malformed JSON input', previous: $e);\n}","preventionTips":["Validate the string with json_validate()/json_decode before decoding it downstream.","For JWTs, base64url-decode each dot-separated segment before JSON decoding and check the token has exactly 3 segments.","Log the previous JsonException message (it includes the exact JSON syntax error and offset).","Ensure HTTP clients send Content-Type: application/json and that proxies don't inject HTML error pages into bodies.","Watch for invalid UTF-8: run mb_check_encoding($raw, 'UTF-8') on data from external sources."],"tags":["json","decoding","php"],"backgroundTag":"json-decode-failed","analyzedSha":"375813049c24c7111bda8b6884c57b071ceb2fe7","analyzedAt":"2026-09-14T11:12:28.004Z","contentChangedAt":"2026-09-14T11:12:28.004Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}