passbolt/passbolt_api · error · Exception
The subscription cannot be verified. Parse error.
Error message
The subscription cannot be verified. Parse error.
What it means
The subscription key was successfully base64-decoded and its OpenPGP signature verified, but the signed payload is not valid JSON (json_decode returned null). The SubscriptionKeyAsciiForm.parse() method throws this because it cannot extract subscription metadata (customer_id, expires, etc.) from a payload it cannot decode.
Solutions
- Re-copy the subscription key exactly as delivered by passbolt (it is a single base64 string) and retry.
- Verify the key has no stray characters, line breaks inside, or truncation: `echo '<key>' | base64 -d | gpg --list-packets` should show a signature packet with a JSON literal payload.
- Request a new subscription key from passbolt support/account if the payload is genuinely corrupt.
- Check that the key matches your edition (CE vs EE) and passbolt version; very old key formats may not decode to the expected JSON.
Example fix
// before (corrupted pasted key)
$this->Subscriptions->createOrUpdate($uac, 'gAAAA...tRU NCOPIED FROM EMAIL WITH LINE BREAKS');
// after
$key = trim(preg_replace('/\s+/', '', $keyFromEmail));
$this->Subscriptions->createOrUpdate($uac, $key); Defensive patterns
Strategy: try-catch
Validate before calling
$decoded = base64_decode($key, true);
if ($decoded === false || strpos($decoded, 'BEGIN PGP MESSAGE') === false) { /* reject before parse */ } Try / catch
try {
$dto = $form->parse($key);
} catch (\Exception $e) {
Log::error('Subscription key payload not decodable: ' . $e->getMessage());
// prompt user to re-copy the key verbatim
} Prevention
- Never manually edit or reformat the subscription key text
- Copy the key from the original source as one continuous base64 string
- Validate locally with `base64 -d` before submitting
When it happens
Trigger: Calling parse() or executing the form with a key whose signed payload was corrupted or truncated after base64 decoding — e.g. the key was manually re-typed, copy-pasted partially, or altered so the verified plaintext is no longer well-formed JSON.
Common situations: A subscription key pasted into a spreadsheet or email that mangled whitespace/characters; using a key from a different product or an outdated format; shell/heredoc escaping damage when inserting the key via CLI; a key issued for a different passbolt edition.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- The subscription format is not valid. Invalid format.
- The subscription key cannot be verified.
- Only administrators can delete the subscription.
- Subscription key could not be found.
- The subscription format is not valid.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/3ce097528a6a9107.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltEe/Subscription/src/Form/SubscriptionKeyAsciiForm.php:141
/**
* Parse the subscription.
*
* @param string|null $keyAscii key in ascii.
* @return \Passbolt\Subscription\Model\Dto\SubscriptionKeyDto
* @throws \Exception If the subscription format is not valid
*/
public function parse(?string $keyAscii = null): SubscriptionKeyDto
{
if (empty($keyAscii) && !empty($this->getData('key_ascii'))) {
$keyAscii = $this->getData('key_ascii');
}
$armoredSignedSubscription = $this->getArmoredSignedSubscription($keyAscii);
$subscriptionInfoStr = $this->_verifySignature($armoredSignedSubscription);
$subscriptionInfo = json_decode($subscriptionInfoStr, true);
if (is_null($subscriptionInfo)) {
throw new Exception(__('The subscription cannot be verified. Parse error.'));
}
$subscriptionInfo['data'] = trim($keyAscii);
return SubscriptionKeyDto::createFromArray($subscriptionInfo);
}
/**
* Get the armored subscription.
*
* @param string $keyAscii key in ascii
* @return string The armored signed subscription
* @throws \Exception If the subscription format is not valid
*/
public function getArmoredSignedSubscription(string $keyAscii): string
{
$armoredSignedSubscription = base64_decode($keyAscii);
if (!$armoredSignedSubscription) {View on GitHub (pinned to 31c1bbc10f)