passbolt/passbolt_api · error · InternalErrorException

The config for the server private key passphrase is invalid.

Error message

The config for the server private key passphrase is invalid.

What it means

Passbolt loads the server GPG key passphrase from the Configure key `passbolt.gpg.serverKey.passphrase` before using the server key to encrypt, decrypt, verify or sign. assertServerPassphrase() requires this value to be a PHP string; if it is missing, null, an integer, or any other non-string type, an InternalErrorException (HTTP 500) is thrown. This is a server-side configuration error, not a user input problem.

Solutions

  1. Define the passphrase as a string in config: Configure::write('passbolt.gpg.serverKey.passphrase', 'your-passphrase'), or in app.php under 'passbolt' => 'gpg' => 'serverKey' => 'passphrase'.
  2. If the passphrase comes from an environment variable, ensure it is exported in the container/webserver (e.g. PASSBOLT_GPG_SERVERKEY_PASSPHRASE) and loaded via env()->read before Configure is populated.
  3. If the server key has no passphrase, explicitly set the config to an empty string '' rather than leaving the key unset.
  4. Clear the config/cache after editing (bin/cake cache clear_all) and restart PHP-FPM/webserver so the new Configure value is read.
  5. Run bin/cake passbolt healthcheck to confirm the server key fingerprint and passphrase configuration are detected correctly.

Example fix

// before (app.php)
'passbolt' => [
    'gpg' => [
        'serverKey' => [
            'fingerprint' => '<FINGERPRINT>',
            // passphrase key missing -> null -> InternalErrorException
        ],
    ],
],
// after
'passbolt' => [
    'gpg' => [
        'serverKey' => [
            'fingerprint' => '<FINGERPRINT>',
            'passphrase' => 'my-secret-passphrase', // string, use '' if key is unprotected
        ],
    ],
],
Defensive patterns

Strategy: validation

Validate before calling

$passphrase = Configure::read('passbolt.gpg.serverKey.passphrase');
if (!is_string($passphrase)) {
    throw new RuntimeException(
        'passbolt.gpg.serverKey.passphrase must be a string, got: '
        . get_debug_type($passphrase)
    );
}

Type guard

function isServerKeyPassphraseSet(mixed $value): bool
{
    return is_string($value);
}

Try / catch

try {
    $gpg = $this->setEncryptKeyWithServerKey($gpg);
} catch (InternalErrorException $e) {
    if (str_contains($e->getMessage(), 'passphrase')) {
        // config problem: fail fast with actionable message
        throw new RuntimeException('Server key passphrase not configured as a string.', 0, $e);
    }
    throw $e;
}

Prevention

When it happens

Trigger: Calling setEncryptKeyWithServerKey, setDecryptKeyWithServerKey, setVerifyKeyWithServerKey or setSignKeyWithServerKey while Configure::read('passbolt.gpg.serverKey.passphrase') returns a non-string value (typically null because the config key is absent, e.g. config/app.php or environment variable PASSBOLT_GPG_SERVERKEY_PASSPHRASE not set).

Common situations: Fresh passbolt install where the server key passphrase entry was removed from config; Docker/Kubernetes deployments where the env var is not injected or set to an empty value that gets cast; passing an integer passphrase (e.g. a purely numeric passphrase quoted in one config file but not another); config cache stale after changing app.php.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

Thrown at src/Service/OpenPGP/OpenPGPCommonServerOperationsTrait.php:176

     */
    private function assertServerFingerprint(mixed $fingerprint): void
    {
        if (!is_string($fingerprint) || !PublicKeyValidationService::isValidFingerprint($fingerprint)) {
            $msg = __('The config for the server private key fingerprint is not available or incomplete.');
            throw new InternalErrorException($msg);
        }
    }

    /**
     * @param mixed $passphrase passphrase
     * @return void
     * @throws \Cake\Http\Exception\InternalErrorException if the server key passphrase cannot be loaded
     */
    private function assertServerPassphrase(mixed $passphrase): void
    {
        if (!is_string($passphrase)) {
            $msg = __('The config for the server private key passphrase is invalid.');
            throw new InternalErrorException($msg);
        }
    }
}

View on GitHub (pinned to 31c1bbc10f)