phalcon/cphalcon · error · Phalcon\Support\Helper\Json\Exceptions\JsonDecodeError

json_decode error: {message}

Error message

json_decode error: {message}

What it means

Phalcon\Support\Helper\Json\Decode wraps json_decode with throw-on-error semantics and rethrows any JsonException as Phalcon\Support\Helper\Json\Exceptions\JsonDecodeError ("json_decode error: {message}"), preserving the code and the previous exception. It fires for exactly the reasons json_decode() fails: syntax errors, unexpected tokens, or nesting deeper than the $depth argument (default 512). Also reachable via HelperFactory as 'jsonDecode'.

Source

Thrown at phalcon/Support/Helper/Json/Decode.zep:51

    /**
     * @param int<1, max> $depth       Recursion depth.
     *
     * @throws JsonDecodeError if the JSON cannot be decoded.
     * @link https://www.php.net/manual/en/function.json-decode.php
     */
    public function __invoke(
        string data,
        bool associative = false,
        int depth = 512,
        int options = 79
    ) {
        var ex;

        try {
            return this->toDecode(data, associative, depth, options);
        } catch JsonException, ex {
            throw new JsonDecodeError(ex->getMessage(), ex->getCode(), ex);
        }
    }
}

View on GitHub (pinned to b7419de9cd)

Solutions

  1. Validate before decoding: json_validate($raw) on PHP >= 8.3, or a decode-and-check-json_last_error probe
  2. Check the upstream response status and Content-Type before treating the body as JSON
  3. Pass a larger $depth for deeply nested documents
  4. Strip BOM/whitespace: $raw = preg_replace('/^\xEF\xBB\xBF/', '', trim($raw));

Example fix

// before
$data = (new Decode())($response->getBody()); // 'json_decode error: Syntax error'

// after
$raw = trim($response->getBody());
if (json_validate($raw)) { // PHP 8.3+
    $data = (new Decode())($raw);
} else {
    $logger->error('Non-JSON body: ' . substr($raw, 0, 200));
    $data = [];
}
Defensive patterns

Strategy: validation

Validate before calling

$raw = trim($response->getBody());

if (json_validate($raw)) { // PHP 8.3+; older: decode + json_last_error check
    $data = (new Decode())($raw);
} else {
    $logger->error('Non-JSON body: ' . substr($raw, 0, 200));
    $data = [];
}

Type guard

function isJsonString(string $raw): bool
{
    json_decode($raw);

    return JSON_ERROR_NONE === json_last_error();
}

Try / catch

use Phalcon\Support\Helper\Json\Exceptions\JsonDecodeError;

try {
    $data = $decode($raw);
} catch (JsonDecodeError $e) {
    // "json_decode error: Syntax error" etc.; previous holds the JsonException
    $data = null;
    $logger->error($e->getMessage());
}

Prevention

When it happens

Trigger: (new Decode())('{"a":') or $helpers->jsonDecode($raw) where $raw is an HTML error page from an upstream API ('Syntax error'); a JSON body truncated by a size limit; nesting beyond 512 levels.

Common situations: Remote APIs returning HTML or empty bodies on 5xx, gateway error pages, BOM-prefixed UTF-8 exports, payloads cut off by proxy/body-size limits, strings with smart quotes pasted into 'JSON' files.

Related errors


AI-assisted analysis of phalcon/cphalcon@b7419de9cd (2026-08-21). Data as JSON: /api/errors/50e23fad94ae88de. Report an issue: GitHub.