lcobucci/jwt · error · Lcobucci\JWT\Encoding\CannotEncodeContent
Error while encoding to JSON
Error message
Error while encoding to JSON
What it means
JoseEncoder::jsonEncode() calls json_encode with JSON_THROW_ON_ERROR (plus JSON_UNESCAPED_SLASHES and JSON_UNESCAPED_UNICODE). If encoding fails, JsonException is caught and rethrown as CannotEncodeContent::jsonIssues($exception) with the message 'Error while encoding to JSON'. Common causes are malformed UTF-8, resources/closures/inf/nan values, or exceeding recursion/depth limits.
Solutions
- Inspect the chained JsonException via $e->getPrevious() (it carries the precise json_encode error code, e.g. JSON_ERROR_UTF8) to identify the offending value.
- Sanitize input to valid UTF-8 (e.g. mb_convert_encoding($value, 'UTF-8', 'UTF-8') or remove invalid sequences) before encoding.
- Remove non-scalar claim values (resources, closures) and replace INF/NAN with finite values.
- Reduce nesting depth below json_encode's 512-level limit for deeply nested payloads.
Example fix
// before
$token = $builder->withClaim('data', $rawFromDb)->getToken(...); // CannotEncodeContent
// after
$data = mb_convert_encoding($rawFromDb, 'UTF-8', 'UTF-8');
$token = $builder->withClaim('data', $data)->getToken(...); Defensive patterns
Strategy: try-catch
Validate before calling
// Cheap pre-checks for the common failure modes
function isJsonEncodableSafe(mixed $value): bool
{
if (is_string($value) && !preg_match('//u', $value)) {
return false; // invalid UTF-8
}
if (is_float($value) && (is_infinite($value) || is_nan($value))) {
return false;
}
return is_scalar($value) || $value === null || is_array($value);
} Try / catch
use Lcobucci\JWT\Encoding\CannotEncodeContent;
try {
$json = $encoder->jsonEncode($data);
} catch (CannotEncodeContent $e) {
$jsonError = $e->getPrevious(); // JsonException with the precise json_encode error
// sanitize/reject $data based on $jsonError->getCode()
} Prevention
- Force UTF-8 on all strings (especially from databases or external APIs) before using them as JWT claims.
- Never place resources, closures, INF/NAN floats, or deeply nested (>512 levels) structures in claims.
- Run json_encode with JSON_THROW_ON_ERROR on the same data first in development to catch issues early.
- Keep the previous JsonException (getPrevious()) in logs — its code pinpoints the exact encoding problem.
When it happens
Trigger: Passing data to jsonEncode() that json_encode cannot serialize: strings with invalid UTF-8, INF/NAN floats, resources or closures, or structures deeper than 512 levels (depth limit).
Common situations: Injecting claims built from raw binary or invalid-encoding database content into a JWT; accidentally putting a resource (e.g. from fopen) in a claim; deeply nested arrays from decoded payloads; locale/encoding mismatches producing non-UTF-8 strings.
Understand the failure class
Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.
Related errors
- Error while decoding from Base64Url, invalid base64…
- No constraint given.
- Error while decoding from JSON
- Invalid signature length.
- Key provided is shorter than
AI-assisted analysis of lcobucci/jwt@375813049c (2026-09-14).
Data as JSON: /api/errors/a5674de7595e691c.
Report an issue: GitHub.
Appendix: source
Thrown at src/Encoding/JoseEncoder.php:28
use function json_decode;
use function json_encode;
use const JSON_THROW_ON_ERROR;
use const JSON_UNESCAPED_SLASHES;
use const JSON_UNESCAPED_UNICODE;
/**
* A utilitarian class that encodes and decodes data according to JOSE specifications
*/
final readonly class JoseEncoder implements Encoder, Decoder
{
public function jsonEncode(mixed $data): string
{
try {
return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR);
} catch (JsonException $exception) {
throw CannotEncodeContent::jsonIssues($exception);
}
}
public function jsonDecode(string $json): mixed
{
try {
return json_decode(json: $json, associative: true, flags: JSON_THROW_ON_ERROR);
} catch (JsonException $exception) {
throw CannotDecodeContent::jsonIssues($exception);
}
}
public function base64UrlEncode(string $data): string
{
return SodiumBase64Polyfill::bin2base64(
$data,
SodiumBase64Polyfill::SODIUM_BASE64_VARIANT_URLSAFE_NO_PADDING,
);View on GitHub (pinned to 375813049c)