passbolt/passbolt_api · critical · InternalErrorException
No default expiry or expiry for token type
Error message
No default expiry or expiry for token type
What it means
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.
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.
Example fix
// before (config/passbolt.php)
'auth' => [],
// after
'auth' => [
'tokenExpiry' => '1 month',
], Defensive patterns
Strategy: validation
Validate before calling
$expiry = Configure::read('passbolt.auth.tokenExpiry');
if (!is_string($expiry) || $expiry === '') {
Configure::write('passbolt.auth.tokenExpiry', '1 month');
} Try / catch
try {
$expiry = $this->authTokenExpiry->getExpiryForTokenType($type);
} catch (\Cake\Http\Exception\InternalErrorException $e) {
Log::error('Missing auth token expiry config: ' . $e->getMessage());
$expiry = '1 month'; // safe default
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.
Related errors
- Could not enable Duo MFA provider.
- Could not enable Duo MFA provider.
- Could not login using Duo MFA provider.
- Invalid public key validation rules are missing.
- The class is not a valid plugin.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/84d48ccfde4b9b4d.
Report an issue: GitHub.
Appendix: source
Thrown at src/Utility/AuthToken/AuthTokenExpiry.php:50
if (!in_array($tokenType, AuthenticationTokensTable::ALLOWED_TYPES)) {
throw new InvalidArgumentException(
sprintf(
'Invalid $tokenType `%s`. Must be one of `%s`.',
$tokenType,
implode(',', AuthenticationTokensTable::ALLOWED_TYPES)
)
);
}
$tokenTypeExpiry = Configure::read(sprintf('passbolt.auth.token.%s.expiry', $tokenType));
if (!is_string($tokenTypeExpiry)) {
$tokenTypeExpiry = Configure::read('passbolt.auth.tokenExpiry');
}
if (!is_string($tokenTypeExpiry)) {
$msg = 'No default expiry or expiry for token type ' . $tokenTypeExpiry;
throw new InternalErrorException($msg);
}
return $tokenTypeExpiry;
}
}
View on GitHub (pinned to 31c1bbc10f)