{"record":{"id":"712fbfcb9c1b57ba","repo":"phalcon/cphalcon","slug":"json-last-error-msg","errorCode":null,"errorMessage":"json_last_error_msg()","messagePattern":"json_last_error_msg\\(\\)","errorType":"exception","errorClass":"\\JsonException","httpStatus":null,"severity":"error","filePath":"phalcon/Traits/Support/Helper/Json/DecodeTrait.zep","lineNumber":57,"sourceCode":"        var decoded, error, message;\n\n        /**\n         * Need to clear the json_last_error() before the code below\n         */\n        let decoded = json_encode(null),\n            decoded = json_decode(data, associative, depth, options),\n            error   = json_last_error(),\n            message = json_last_error_msg();\n\n        /**\n         * When JSON_THROW_ON_ERROR is set, json_decode() has already raised a\n         * native \\JsonException above; otherwise the error is surfaced the\n         * same way here.\n         */\n        if (JSON_ERROR_NONE !== error) {\n            json_encode(null);\n\n            throw new \\JsonException(message, error);\n        }\n\n        return decoded;\n    }\n}\n","sourceCodeStart":39,"sourceCodeEnd":63,"githubUrl":"https://github.com/phalcon/cphalcon/blob/b7419de9cd0a8a3f48441ead84c9f8415d463e25/phalcon/Traits/Support/Helper/Json/DecodeTrait.zep#L39-L63","documentation":"Phalcon's JSON decode helper (Phalcon\\Support\\Helper\\Json\\Decode, via DecodeTrait::toDecode) wraps json_decode and converts any parse failure into a native \\JsonException whose message comes from json_last_error_msg() — e.g. 'Syntax error', 'Maximum stack depth exceeded', 'Malformed UTF-8' (phalcon/Traits/Support/Helper/Json/DecodeTrait.zep:57). This guarantees JSON_THROW_ON_ERROR-like behavior even when the caller did not pass that flag.","triggerScenarios":"Decode::__invoke($json) with truncated JSON (cookie cut off, partial HTTP body), single-quoted strings or unquoted keys, BOM/invalid UTF-8 bytes, or nesting deeper than the default 512 depth. Note UserRemember and similar consumers call this internally but catch InvalidArgumentException, so raw uses of Decode are where this surfaces.","commonSituations":"Reading remember-me/session cookies that were truncated or tampered with; API responses cut by proxies or timeouts; payloads stored with binary or legacy-encoded (latin1) data; hand-built JSON strings instead of json_encode output.","solutions":["Catch \\JsonException wherever the input is untrusted and fall back to a safe default.","On PHP 8.3+, pre-validate with json_validate($json, $depth) before decoding.","Fix the producer: encode with json_encode, send correct Content-Length, use JSON_INVALID_UTF8_SUBSTITUTE on the encode side."],"exampleFix":"// before\n$data = (new Decode())->__invoke($cookieValue); // throws JsonException on bad JSON\n\n// after\ntry {\n    $data = (new Decode())->__invoke($cookieValue);\n} catch (\\JsonException $e) {\n    $data = [];\n}","handlingStrategy":"try-catch","validationCode":"if (PHP_VERSION_ID >= 80300 && !json_validate($json)) {\n    $json = '{}'; // reject early with a known-good default\n}\n$data = (new Decode())->__invoke($json, true);","typeGuard":null,"tryCatchPattern":"try {\n    $data = (new Decode())->__invoke($payload, true);\n} catch (\\JsonException $e) {\n    $logger->warning('Invalid JSON: ' . $e->getMessage());\n    $data = []; // safe default for untrusted input\n}","preventionTips":["Never hand-build JSON strings; produce it with json_encode.","On PHP 8.3+ use json_validate() to check before decoding untrusted input.","Pass an explicit depth when you expect deeply nested payloads instead of relying on 512."],"tags":["phalcon","json","decode","jsonexception","malformed-input"],"backgroundTag":"json-decode-error","analyzedSha":"b7419de9cd0a8a3f48441ead84c9f8415d463e25","analyzedAt":"2026-08-21T06:21:18.811Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}