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
- Ensure the Gpgkey entity passed to setEncryptKeyWithUserKey/setVerifyKeyWithUserKey contains both armored_key and fingerprint (check the table query's select/contain).
- If the key is genuinely missing, verify the user completed the OpenPGP key setup (gpgkeys record exists and is complete) before invoking encrypted operations.
- Catch InternalErrorException and surface a meaningful message instead of leaking a 500 to the client.
- 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
- Always load full Gpgkey entities; avoid select() that drops armored_key or fingerprint.
- Assert key completeness in a shared guard before any OpenPGP operation.
- Add a data health check that reports gpgkeys rows missing armored_key/fingerprint.
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
- The user armored key is not available or incomplete.
- A valid OpenPGP key must be provided.
- Could not import the user OpenPGP key.
- Could not import the user OpenPGP key.
- Could not validate message data.
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)