passbolt/passbolt_api · critical · InvalidJwtKeyPairException

The key pair for JWT Authentication is not complete.

Error message

The key pair for JWT Authentication is not complete.

What it means

Thrown by JwtAbstractService::readKeyFileContent when the configured JWT key file path is not readable (is_readable() returns false). Raised as InvalidJwtKeyPairException, indicating the JWT authentication key pair is missing or inaccessible.

Solutions

  1. Generate the key pair: bin/cake passbolt create_jwt_keys
  2. Fix permissions: chown www-data:www-data config/jwt/*.pem && chmod 640 config/jwt/*.pem (and 750 on the directory)
  3. Ensure config/jwt exists and the path in configuration points to the real key location
  4. In containerized setups, verify the secret volume is mounted and readable by the PHP user

Example fix

// before
// config/jwt/ missing or unreadable
// after
bin/cake passbolt create_jwt_keys
chown -R www-data:www-data config/jwt && chmod 750 config/jwt && chmod 640 config/jwt/*.pem
Defensive patterns

Strategy: validation

Validate before calling

$path = config('passbolt.jwt.keyPath');
if (!is_file($path) || !is_readable($path)) failFast('JWT key missing/unreadable: ' . $path);

Try / catch

try { $token = $jwtService->createToken(); } catch (InvalidJwtKeyPairException $e) { runCreateJwtKeys(); }

Prevention

When it happens

Trigger: Any JWT operation (token creation, JWKS retrieval, raw public key read) when config/jwt/jwt.public.key or jwt.private.key does not exist or the web-server user cannot read it.

Common situations: Fresh install where create_jwt_keys was never run; keys not synced across a multi-server deployment; wrong ownership/permissions after deployment; key directory deleted or mounted empty in containers.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/125729396fb0d02e. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltCe/JwtAuthentication/src/Service/AccessToken/JwtAbstractService.php:55

    }

    /**
     * @return string Path to the secret/private key file
     */
    public function getKeyPath(): string
    {
        return $this->keyPath;
    }

    /**
     * @return string|false Content of the secret/private key file
     * @throws \Passbolt\JwtAuthentication\Error\Exception\AccessToken\InvalidJwtKeyPairException if the file is not found or not readable.
     */
    public function readKeyFileContent(): string|false
    {
        if (!is_readable($this->getKeyPath())) {
            $userErrorMessage = __('The key pair for JWT Authentication is not complete.');
            throw new InvalidJwtKeyPairException($userErrorMessage);
        }

        return file_get_contents($this->getKeyPath());
    }
}

View on GitHub (pinned to 31c1bbc10f)