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

  1. Verify the file exists and is readable by the PHP process (is_readable, ls -l, correct user/group)
  2. Confirm the file contains a valid PEM key (openssl pkey -in key.pem -check)
  3. Regenerate/replace a corrupted or empty key file
  4. 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

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


AI-assisted analysis of BookStackApp/BookStack@18f8469a1c (2026-09-02). Data as JSON: /api/errors/d9a8e0089b354a20. Report an issue: GitHub.