{"id":"b1c2d17061b10bac","repo":"laravel/framework","slug":"the-payload-is-invalid","errorCode":null,"errorMessage":"The payload is invalid.","messagePattern":"The payload is invalid\\.","errorType":"exception","errorClass":"DecryptException","httpStatus":null,"severity":"error","filePath":"src/Illuminate/Encryption/Encrypter.php","lineNumber":244,"sourceCode":"     * @return string\n     */\n    protected function hash(#[\\SensitiveParameter] $iv, #[\\SensitiveParameter] $value, #[\\SensitiveParameter] $key)\n    {\n        return hash_hmac('sha256', $iv.$value, $key);\n    }\n\n    /**\n     * Get the JSON array from the given payload.\n     *\n     * @param  string  $payload\n     * @return array\n     *\n     * @throws \\Illuminate\\Contracts\\Encryption\\DecryptException\n     */\n    protected function getJsonPayload($payload)\n    {\n        if (! is_string($payload)) {\n            throw new DecryptException('The payload is invalid.');\n        }\n\n        $payload = json_decode(base64_decode($payload), true);\n\n        // If the payload is not valid JSON or does not have the proper keys set we will\n        // assume it is invalid and bail out of the routine since we will not be able\n        // to decrypt the given value. We'll also check the MAC for this encryption.\n        if (! $this->validPayload($payload)) {\n            throw new DecryptException('The payload is invalid.');\n        }\n\n        return $payload;\n    }\n\n    /**\n     * Verify that the encryption payload is valid.\n     *\n     * @param  mixed  $payload","sourceCodeStart":226,"sourceCodeEnd":262,"githubUrl":"https://github.com/laravel/framework/blob/bd6b5437e6ad87bb49f9b426724f07a9f64e9683/src/Illuminate/Encryption/Encrypter.php#L226-L262","documentation":"getJsonPayload() throws DecryptException('The payload is invalid.') at line 244 when the input is not a string — decrypt() was given null, an array, an int, etc. This is the first guard before any base64/json decoding; it catches callers passing the wrong type entirely (e.g. feeding already-decoded data back into decrypt).","triggerScenarios":"Calling decrypt(null), decrypt([]) or decrypt(123) — typically because the caller read a missing cookie/header (null) or pulled an already-parsed value from somewhere and passed it straight to decrypt(). Common in cookie/session middleware reading optional inputs.","commonSituations":"Cookies not present on the request ($request->cookie('foo') returns null); a header missing; reading encrypted values from JSON requests where the field is absent; double-decoding (passing the decoded array back into decrypt).","solutions":["Check the input is a non-empty string before calling decrypt: if (is_string($v) && $v !== '') { decrypt($v); }.","Use Encrypter::appearsEncrypted($v) to confirm shape before attempting decryption.","Treat null/missing inputs as 'no data' in your domain logic rather than piping them through decrypt().","For optional cookies/headers, return a default and skip decryption when absent."],"exampleFix":"// before\n$value = decrypt($request->cookie('prefs')); // cookie may be null\n\n// after\n$raw = $request->cookie('prefs');\n$value = is_string($raw) && Encrypter::appearsEncrypted($raw)\n    ? decrypt($raw)\n    : defaultPrefs();","handlingStrategy":"type-guard","validationCode":"$raw = $request->cookie('prefs');\nif (! is_string($raw) || $raw === '') {\n    return defaultPrefs();\n}\nreturn decrypt($raw);","typeGuard":"function isDecryptableString(mixed $value): bool\n{\n    return is_string($value) && $value !== ''\n        && \\Illuminate\\Encryption\\Encrypter::appearsEncrypted($value);\n}","tryCatchPattern":null,"preventionTips":["Never pass null/arrays/ints into decrypt() — guard with is_string first.","Treat missing optional inputs as defaults, not as decrypt targets.","Use appearsEncrypted() to validate shape before decryption."],"tags":["encryption","decryption","validation","input-handling"],"analyzedSha":"bd6b5437e6ad87bb49f9b426724f07a9f64e9683","analyzedAt":"2026-08-06T00:28:32.783Z","schemaVersion":2}