phalcon/cphalcon · error · Phalcon\Support\Helper\Json\Exceptions\JsonEncodeError
json_encode error: {message}
Error message
json_encode error: {message} What it means
Phalcon\Support\Helper\Json\Encode wraps json_encode with throw-on-error semantics and rethrows any JsonException as Phalcon\Support\Helper\Json\Exceptions\JsonEncodeError ("json_encode error: {message}"). It fires when json_encode fails: malformed UTF-8 in strings ('Malformed UTF-8 characters, possibly incorrectly encoded'), NAN/INF floats, resources, arrays with mixed keys? no — primarily recursion ('Recursion detected') and depth over 512.
Source
Thrown at phalcon/Support/Helper/Json/Encode.zep:52
use EncodeTrait;
/**
* @param int<1, max> $depth Recursion depth.
*
* @throws JsonEncodeError if the JSON cannot be encoded.
* @link https://www.php.net/manual/en/function.json-encode.php
*/
public function __invoke(
var data,
int options = 79,
int depth = 512
) -> string {
var ex;
try {
return this->toEncode(data, options, depth);
} catch JsonException, ex {
throw new JsonEncodeError(ex->getMessage(), ex->getCode(), ex);
}
}
}
View on GitHub (pinned to b7419de9cd)
Solutions
- Fix data encoding at the source: set UTF-8 on DB connections/files, or repair strings with mb_convert_encoding($v, 'UTF-8', 'UTF-8')
- Replace non-finite floats: is_finite($v) ? $v : null
- For circular graphs, implement JsonSerializable or unset back-references; raise $depth for legitimately deep structures
- As a last resort pass JSON_PARTIAL_OUTPUT_ON_ERROR via $options and accept placeholder output
Example fix
// before
$json = (new Encode())($row); // 'json_encode error: Malformed UTF-8 characters'
// after
array_walk_recursive($row, function (&$v) {
if (is_string($v) && !mb_check_encoding($v, 'UTF-8')) {
$v = mb_convert_encoding($v, 'UTF-8', 'UTF-8');
} elseif (is_float($v) && !is_finite($v)) {
$v = null;
}
});
$json = (new Encode())($row); Defensive patterns
Strategy: validation
Validate before calling
array_walk_recursive($data, function (&$value) {
if (is_float($value) && !is_finite($value)) {
$value = null; // NAN/INF are not JSON-encodable
} elseif (is_string($value) && !mb_check_encoding($value, 'UTF-8')) {
$value = mb_convert_encoding($value, 'UTF-8', 'UTF-8');
} elseif (is_resource($value)) {
$value = null;
}
});
$json = (new Encode())($data); Type guard
function isJsonEncodableValue($value): bool
{
if (is_float($value)) {
return is_finite($value);
}
return !is_resource($value)
&& (!is_string($value) || mb_check_encoding($value, 'UTF-8'));
} Try / catch
use Phalcon\Support\Helper\Json\Exceptions\JsonEncodeError;
try {
$json = $encode($data);
} catch (JsonEncodeError $e) {
// "json_encode error: Malformed UTF-8 characters..." / "Recursion detected"
$logger->error($e->getMessage());
$json = null;
} Prevention
- Set UTF-8 end to end: DB connection charset, file reads, HTTP output
- Reject or substitute non-finite floats before data reaches encoders
- Implement JsonSerializable on entities with back-references instead of relying on deep casting
- Raise $depth deliberately for known-deep structures rather than hoping 512 suffices
When it happens
Trigger: (new Encode())($row) where $row contains a latin1-bytes string from a misconfigured DB column; encoding a graph with circular references (parent/child objects cast to arrays); NAN/INF leaking from calculations; depth > 512.
Common situations: DB connections not set to UTF-8 producing invalid byte sequences; scientific/financial feeds delivering INF/NAN; entity graphs with back-references being serialized for caches or APIs.
Related errors
- json_decode error: {message}
- json_last_error_msg()
- Configuration file {fileName} cannot be loaded
- Configuration file {fileName} cannot be loaded
- Unknown method: [{method}]
AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21).
Data as JSON: /api/errors/3daff860dcab51db.
Report an issue: GitHub.