BookStackApp/BookStack · error · OidcInvalidKeyException
Failed to load key from file path with error: {$exception->g
Error message
Failed to load key from file path with error: {$exception->getMessage()} What it means
loadFromPath reads the file at the 'file://' path and hands the contents to phpseclib's PublicKeyLoader. If reading or parsing fails (unreadable file, missing file, malformed key), the underlying exception message is wrapped in OidcInvalidKeyException with this message.
Source
Thrown at app/Access/Oidc/OidcJwtSigningKey.php:43
$this->loadFromJwkArray($jwkOrKeyPath);
} elseif (str_starts_with($jwkOrKeyPath, 'file://')) {
$this->loadFromPath($jwkOrKeyPath);
} else {
throw new OidcInvalidKeyException('Unexpected type of key value provided');
}
}
/**
* @throws OidcInvalidKeyException
*/
protected function loadFromPath(string $path): void
{
try {
$key = PublicKeyLoader::load(
file_get_contents($path)
);
} catch (\Exception $exception) {
throw new OidcInvalidKeyException("Failed to load key from file path with error: {$exception->getMessage()}");
}
if (!$key instanceof RSA) {
throw new OidcInvalidKeyException('Key loaded from file path is not an RSA key as expected');
}
$this->key = $key->withPadding(RSA::SIGNATURE_PKCS1);
}
/**
* @throws OidcInvalidKeyException
*/
protected function loadFromJwkArray(array $jwk): void
{
// 'alg' is optional for a JWK, but we will still attempt to validate if
// it exists otherwise presume it will be compatible.
$alg = $jwk['alg'] ?? null;
if ($jwk['kty'] !== 'RSA' || !(is_null($alg) || $alg === 'RS256')) {View on GitHub (pinned to 18f8469a1c)
Solutions
- Verify the file exists and is readable by the PHP process (is_readable, ls -l, correct user/group)
- Confirm the file contains a valid PEM key (openssl pkey -in key.pem -check)
- Regenerate/replace a corrupted or empty key file
- If the key is encrypted, provide the passphrase-compatible loader or decrypt it first
Example fix
// before (path typo / unreadable)
$key = new OidcJwtSigningKey('file:///etc/oidc/key.pem');
// after: verify then construct
if (!is_readable('/etc/oidc/key.pem')) { throw new \RuntimeException('key missing'); }
$key = new OidcJwtSigningKey('file:///etc/oidc/key.pem'); Defensive patterns
Strategy: try-catch
Validate before calling
$path = substr($value, strlen('file://'));
if (!is_file($path) || !is_readable($path)) { throw new \RuntimeException("key file missing or unreadable: $path"); }
openssl_pkey_get_public('file://' . $path) ?: throw new \RuntimeException('unparseable key file'); Try / catch
try { $key = new OidcJwtSigningKey('file://' . $path); } catch (OidcInvalidKeyException $e) { log_error($e->getMessage()); throw $e; } // message includes underlying loader error Prevention
- Deploy key files with correct ownership/permissions for the PHP user
- Verify key PEM validity in CI (openssl pkey -check)
- Use absolute paths and confirm them in the deployment environment
- Never ship empty or placeholder key files
When it happens
Trigger: new OidcJwtSigningKey('file://...') where the path does not exist, is not readable (permissions), is empty, or contains data PublicKeyLoader cannot parse.
Common situations: Wrong path in config (relative vs absolute); file deployed without correct permissions; key file truncated or corrupted during deploy; unsupported key format (e.g. encrypted key without passphrase, or non-PEM blob).
Related errors
- Failed to load key from JWK parameters with error: {$excepti
- Unexpected type of key value provided
- Key loaded from file path is not an RSA key as expected
- Could not parse out a valid {$prop} within the provided toke
- Could not parse out a valid signature within the provided to
AI-assisted analysis of BookStackApp/BookStack@18f8469a1c (2026-09-02).
Data as JSON: /api/errors/d9a8e0089b354a20.
Report an issue: GitHub.