passbolt/passbolt_api · error · BadRequestException

The subscription key cannot be verified.

Error message

The subscription key cannot be verified.

What it means

SubscriptionKeySaveService::save threw SubscriptionSignatureException, meaning the submitted subscription key's cryptographic signature failed verification — the key is invalid, corrupted, or not a genuine passbolt-issued license. The controller surfaces it as a 400 with this message.

Solutions

  1. Re-copy the subscription key exactly as delivered, including the full PGP MESSAGE armor blocks
  2. Re-download the key from the passbolt customer portal
  3. Confirm the key matches your subscription/organization ID and is for the passbolt product
  4. Contact passbolt support if a freshly issued key still fails signature verification

Example fix

// before
data=-----BEGIN PGP MESSAGE-----
...truncated block...
// after
data=-----BEGIN PGP MESSAGE-----
<full, unmodified armored subscription key>
-----END PGP MESSAGE-----
Defensive patterns

Strategy: validation

Validate before calling

const key = fs.readFileSync('subscription_key.txt', 'utf8').trim();
if (!key.startsWith('-----BEGIN PGP MESSAGE-----') || !key.endsWith('-----END PGP MESSAGE-----')) {
  throw new Error('Subscription key armor incomplete — re-copy the full key');
}

Try / catch

const res = await saveKey(key);
if (res.status === 400 && res.body.message.includes('cannot be verified')) {
  console.error('Key signature invalid: re-download the key and retry without editing it');
}

Prevention

When it happens

Trigger: POST/PUT /subscription.jsonapi where the key text was truncated, line-wrapped/altered in transit, hand-edited, or simply not a valid passbolt subscription key.

Common situations: Copy/paste losing PGP message lines; email client re-wrapping the armored key; pasting a key for a different product or customer; attempting to forge/modify an existing key.

Understand the failure class

Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — 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/f777734ebd1d1b4e. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltEe/Subscription/src/Controller/Subscriptions/SubscriptionsUpdateController.php:49

{
    /**
     * @return void
     */
    public function update(): void
    {
        if (!$this->User->isAdmin()) {
            throw new ForbiddenException(__('You are not allowed to access this location.'));
        }

        $keyString = $this->getRequest()->getData('data');
        if (!is_string($keyString) || trim($keyString) === '') {
            throw new BadRequestException(__('Subscription key data is required.'));
        }

        try {
            $keyDto = (new SubscriptionKeySaveService())->save($keyString, $this->User->getAccessControl());
        } catch (SubscriptionSignatureException $e) {
            throw new BadRequestException($e->getMessage());
        } catch (SubscriptionException $e) {
            throw new PaymentRequiredException($e->getMessage(), $e->getErrors());
        }

        // POST and PUT both land here for backwards compatibility.
        // Preserve the historical success messages of the now-deleted
        // SubscriptionsCreateController (POST) and this controller (PUT) so the
        // legacy SubscriptionsCreateControllerTest keeps passing unchanged.
        $message = $this->getRequest()->is('post')
            ? __('The subscription was created.')
            : __('The subscription was updated.');

        $this->success($message, $keyDto->toArray());
    }
}

View on GitHub (pinned to 31c1bbc10f)