{"record":{"id":"84d48ccfde4b9b4d","repo":"passbolt/passbolt_api","slug":"no-default-expiry-or-expiry-for-token-type-authtokenexpiry","errorCode":null,"errorMessage":"No default expiry or expiry for token type ","messagePattern":"No default expiry or expiry for token type ","errorType":"exception","errorClass":"InternalErrorException","httpStatus":500,"severity":"critical","filePath":"src/Utility/AuthToken/AuthTokenExpiry.php","lineNumber":50,"sourceCode":"        if (!in_array($tokenType, AuthenticationTokensTable::ALLOWED_TYPES)) {\n            throw new InvalidArgumentException(\n                sprintf(\n                    'Invalid $tokenType `%s`. Must be one of `%s`.',\n                    $tokenType,\n                    implode(',', AuthenticationTokensTable::ALLOWED_TYPES)\n                )\n            );\n        }\n\n        $tokenTypeExpiry = Configure::read(sprintf('passbolt.auth.token.%s.expiry', $tokenType));\n\n        if (!is_string($tokenTypeExpiry)) {\n            $tokenTypeExpiry = Configure::read('passbolt.auth.tokenExpiry');\n        }\n\n        if (!is_string($tokenTypeExpiry)) {\n            $msg = 'No default expiry or expiry for token type ' . $tokenTypeExpiry;\n            throw new InternalErrorException($msg);\n        }\n\n        return $tokenTypeExpiry;\n    }\n}\n","sourceCodeStart":32,"sourceCodeEnd":56,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/src/Utility/AuthToken/AuthTokenExpiry.php#L32-L56","documentation":"AuthTokenExpiry.getExpiryForTokenType() looks up the expiry duration for an authentication token type from Configure (passbolt.js authToken expiry or passbolt.auth.tokenExpiry). If neither the token-type-specific value nor the default tokenExpiry is a string, an InternalErrorException is thrown — note the message appends $tokenTypeExpiry which is non-string at that point, often rendering blank.","triggerScenarios":"Requesting expiry for a token type when both passbolt.js.<type>.expiry (or equivalent) and the fallback passbolt.auth.tokenExpiry are unset or non-string (e.g. null, array); loading a config file that omits these keys; a plugin defining a new token type without registering its expiry.","commonSituations":"Custom or third-party auth token plugin missing its expiry config; truncated or hand-edited config/passbolt.php; env var overriding token expiry with a non-string value; upgrade dropping the passbolt.auth.tokenExpiry default.","solutions":["Set the default expiry in config: Configure::write('passbolt.auth.tokenExpiry', '1 month') or define it in config/passbolt.php.","Set a token-type-specific expiry (e.g. Configure::write('passbolt.js.recover.expiry', '1 day')).","Check config/passbolt.default.php for the expected keys and re-add any that were removed during an upgrade.","Ensure the configured value is a string duration, not null/array/integer."],"exampleFix":"// before (config/passbolt.php)\n'auth' => [],\n// after\n'auth' => [\n    'tokenExpiry' => '1 month',\n],","handlingStrategy":"validation","validationCode":"$expiry = Configure::read('passbolt.auth.tokenExpiry');\nif (!is_string($expiry) || $expiry === '') {\n    Configure::write('passbolt.auth.tokenExpiry', '1 month');\n}","typeGuard":null,"tryCatchPattern":"try {\n    $expiry = $this->authTokenExpiry->getExpiryForTokenType($type);\n} catch (\\Cake\\Http\\Exception\\InternalErrorException $e) {\n    Log::error('Missing auth token expiry config: ' . $e->getMessage());\n    $expiry = '1 month'; // safe default\n}","preventionTips":["Always define passbolt.auth.tokenExpiry in config/passbolt.php (copy from config/passbolt.default.php).","Register an expiry for every custom token type introduced by plugins.","Add a bootstrap sanity check that token expiry config values are strings.","After upgrades, diff your config against the new default config for dropped keys."],"tags":["authentication","tokens","configuration","internal-error"],"backgroundTag":"missing-config-value","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}