passbolt/passbolt_api · error · InternalErrorException

The user public key is not available or incomplete.

Error message

The user public key is not available or incomplete.

What it means

InternalErrorException thrown by OpenPGPCommonUserOperationsTrait::assertUserKey when a Gpgkey entity is missing either its armored_key or fingerprint field. The trait uses this guard before configuring the OpenPGP backend with a user key for encryption or verification, since both fields are mandatory to use the key.

Solutions

  1. Ensure the Gpgkey entity passed to setEncryptKeyWithUserKey/setVerifyKeyWithUserKey contains both armored_key and fingerprint (check the table query's select/contain).
  2. If the key is genuinely missing, verify the user completed the OpenPGP key setup (gpgkeys record exists and is complete) before invoking encrypted operations.
  3. Catch InternalErrorException and surface a meaningful message instead of leaking a 500 to the client.
  4. Inspect the gpgkeys table row for the user to confirm armored_key and fingerprint are populated.

Example fix

// before
$userKey = $this->Gpgkeys->find()->where(['user_id' => $userId])->select(['id', 'fingerprint'])->first();
$gpg->setEncryptKeyWithUserKey($userKey);

// after
$userKey = $this->Gpgkeys->find()->where(['user_id' => $userId])->first(); // full entity, includes armored_key
if ($userKey === null || !is_string($userKey->armored_key) || !is_string($userKey->fingerprint)) {
    throw new UserNotFoundException(__('No valid OpenPGP key for this user.'));
}
$gpg->setEncryptKeyWithUserKey($userKey);
Defensive patterns

Strategy: validation

Validate before calling

// PHP
if (!isset($userKey->armored_key) || !isset($userKey->fingerprint)) {
    throw new BadRequestException(__('User OpenPGP key data is incomplete.'));
}
$gpg->setEncryptKeyWithUserKey($userKey);

Type guard

function isCompleteUserKey(\Passbolt\WebInstaller\...\Gpgkey $k): bool {
    return isset($k->armored_key) && isset($k->fingerprint);
}

Try / catch

try {
    $gpg->setEncryptKeyWithUserKey($userKey);
} catch (\Cake\Http\Exception\InternalErrorException $e) {
    $this->log($e->getMessage());
    throw new BadRequestException(__('This user has no usable OpenPGP key.'));
}

Prevention

When it happens

Trigger: Calling setEncryptKeyWithUserKey($userKey) or setVerifyKeyWithUserKey($userKey) with a Gpgkey entity whose armored_key or fingerprint property is null/unset (e.g. entity built with select() omitting those columns, or a partially hydrated entity).

Common situations: Fetching user Gpgkey rows with a fields/select list that excludes armored_key or fingerprint; using a Gpgkey entity constructed manually with only partial data; data corruption or incomplete key import in gpgkeys table.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — 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/117b6a489021bbcb. Report an issue: GitHub.

Appendix: source

Thrown at src/Service/OpenPGP/OpenPGPCommonUserOperationsTrait.php:109

                }
                $msg = __('Could not import the user OpenPGP key.');
                throw new InternalErrorException($msg, 500, $exception);
            }
        }

        return $gpg;
    }

    /**
     * @param \App\Model\Entity\Gpgkey $userKey object as sent from event
     * @return void
     * @throws \Cake\Http\Exception\InternalErrorException if the user key cannot be loaded
     */
    private function assertUserKey(Gpgkey $userKey): void
    {
        if (!isset($userKey->armored_key) || !isset($userKey->fingerprint)) {
            $msg = __('The user public key is not available or incomplete.');
            throw new InternalErrorException($msg);
        }

        $fingerprint = $userKey->fingerprint;
        if (!is_string($fingerprint) || !PublicKeyValidationService::isValidFingerprint($fingerprint)) {
            $msg = __('The user public key fingerprint is not available or incomplete.');
            throw new InternalErrorException($msg);
        }

        $armoredKey = $userKey->armored_key;
        if (!is_string($armoredKey) || !PublicKeyValidationService::parseAndValidatePublicKey($armoredKey)) {
            $msg = __('The user armored key is not available or incomplete.');
            throw new InternalErrorException($msg);
        }
    }
}

View on GitHub (pinned to 31c1bbc10f)