{"record":{"id":"04a9e4fd5af0a7f2","repo":"tymondesigns/jwt-auth","slug":"secret-is-not-set","errorCode":null,"errorMessage":"Secret is not set.","messagePattern":"Secret is not set\\.","errorType":"exception","errorClass":"Tymon\\JWTAuth\\Exceptions\\JWTException","httpStatus":null,"severity":"critical","filePath":"src/Providers/JWT/Lcobucci.php","lineNumber":238,"sourceCode":"    /**\n     * {@inheritdoc}\n     *\n     * @return \\Lcobucci\\JWT\\Signer\\Key\n     *\n     * @throws \\Tymon\\JWTAuth\\Exceptions\\JWTException\n     */\n    protected function getSigningKey()\n    {\n        if ($this->isAsymmetric()) {\n            if (! $privateKey = $this->getPrivateKey()) {\n                throw new JWTException('Private key is not set.');\n            }\n\n            return $this->getKey($privateKey, $this->getPassphrase() ?? '');\n        }\n\n        if (! $secret = $this->getSecret()) {\n            throw new JWTException('Secret is not set.');\n        }\n\n        return $this->getKey($secret);\n    }\n\n    /**\n     * {@inheritdoc}\n     *\n     * @return \\Lcobucci\\JWT\\Signer\\Key\n     *\n     * @throws \\Tymon\\JWTAuth\\Exceptions\\JWTException\n     */\n    protected function getVerificationKey()\n    {\n        if ($this->isAsymmetric()) {\n            if (! $public = $this->getPublicKey()) {\n                throw new JWTException('Public key is not set.');\n            }","sourceCodeStart":220,"sourceCodeEnd":256,"githubUrl":"https://github.com/tymondesigns/jwt-auth/blob/6c70930a92710d97e8e52b182fca2176097f33be/src/Providers/JWT/Lcobucci.php#L220-L256","documentation":"Thrown by getSigningKey() when a symmetric algorithm (HS256/HS384/HS512) is configured and the 'secret' config value is falsy. Since buildConfig() runs in the provider constructor, the JWT service cannot be instantiated at all - the first attempt to issue or verify a token throws, usually surfacing as a 500 on authenticated routes.","triggerScenarios":"JWT_SECRET env var missing or empty in the running environment while JWT_ALGO is HS* (the default). Triggered by resolving auth('api'), calling auth()->login($user) / JWTAuth::fromUser(), or hitting any route behind auth:api middleware for the first time.","commonSituations":"Fresh install where `php artisan jwt:secret` was never run; .env missing the entry locally or on a new server; a deployed environment (Docker, Kubernetes, Forge, Vapor) whose secret variables were not provisioned; php artisan config:cache run before JWT_SECRET was set, so the cached config permanently holds null.","solutions":["Generate and persist a secret: php artisan jwt:secret (writes JWT_SECRET to .env automatically; use --force to overwrite)","Confirm the entry exists in every environment: grep JWT_SECRET .env, and check the platform's env/secret store for production","Run php artisan config:clear after adding the secret (a stale config cache keeps null even once .env is fixed), then re-run config:cache if you use it","Use the same JWT_SECRET across all services that issue or verify these tokens"],"exampleFix":"# before\n# .env has no JWT_SECRET line -> JWTException: Secret is not set.\n\n# after\nphp artisan jwt:secret\n# .env now contains: JWT_SECRET=... (and run: php artisan config:clear)","handlingStrategy":"validation","validationCode":"// Fail fast at boot instead of at the first login attempt\npublic function boot(): void\n{\n    if (in_array(config('jwt.algo'), ['HS256', 'HS384', 'HS512'], true)\n        && empty(config('jwt.secret'))) {\n        throw new RuntimeException('JWT_SECRET is not set - run: php artisan jwt:secret');\n    }\n}","typeGuard":"function hasJwtSecret(): bool\n{\n    return !empty(config('jwt.secret'));\n}","tryCatchPattern":"use Tymon\\JWTAuth\\Exceptions\\JWTException;\n\ntry {\n    $token = auth('api')->login($user);\n} catch (JWTException $e) {\n    // 'Secret is not set.' is an environment problem - alert ops, do not blame the client\n    Log::critical('JWT secret missing', ['env' => app()->environment()]);\n    abort(500, 'token service unavailable');\n}","preventionTips":["Run php artisan jwt:secret as part of every fresh install/CI bootstrap script","Add a health check (e.g. /up) that asserts config('jwt.secret') is non-null in production","After changing .env, always run config:clear (or rebuild config:cache) - stale cache is the most common recurrence","Inject JWT_SECRET via the platform secret store rather than committing .env files"],"tags":["jwt","php","laravel","configuration","missing-secret","env-var"],"backgroundTag":"missing-env-var","analyzedSha":"6c70930a92710d97e8e52b182fca2176097f33be","analyzedAt":"2026-08-21T02:16:37.040Z","schemaVersion":2},"datasetVersion":"2026-08-21T03:17:12.404Z"}