passbolt/passbolt_api · error · SubscriptionRecordNotFoundException

Subscription key could not be found.

Error message

Subscription key could not be found.

What it means

SubscriptionsTable::getOrFail() throws SubscriptionRecordNotFoundException ('Subscription key could not be found.') when the subscriptions table contains no row at all — find()->firstOrFail() finds nothing and the catch converts any failure into this domain exception. It signals that no subscription key has ever been installed on this instance.

Solutions

  1. Install a subscription key: POST /subscription with the base64 key as an admin, or use the passbolt CLI subscription command.
  2. Check the table is not empty: `SELECT * FROM subscriptions;` — if empty, add a valid key.
  3. If a key was recently deleted, re-import it from the passbolt account portal.

Example fix

// before: reading subscription on a fresh install fails
$subscription = $this->Subscriptions->getOrFail();
// after: guard for absence first
try {
    $subscription = $this->Subscriptions->getOrFail();
} catch (SubscriptionRecordNotFoundException $e) {
    // no key installed yet — prompt admin to import one
}
Defensive patterns

Strategy: try-catch

Validate before calling

$exists = $this->Subscriptions->find()->count() > 0;
if (!$exists) { /* no key installed — handle setup flow */ }

Try / catch

try {
    $subscription = $this->Subscriptions->getOrFail();
} catch (SubscriptionRecordNotFoundException $e) {
    // no subscription key installed — show onboarding / import UI
}

Prevention

When it happens

Trigger: Calling getOrFail() (or higher-level reads like the subscription status endpoint) on a fresh passbolt install where no subscription key was imported yet, or after the subscription row was deleted (e.g. via SubscriptionKeyDeleteService).

Common situations: Fresh EE deployment where the admin hasn't posted the subscription key yet; subscription deleted via DELETE /subscription; database restored without the subscriptions row; running license checks during setup before key entry.

Understand the failure class

Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.

Related errors


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

Appendix: source

Thrown at plugins/PassboltEe/Subscription/src/Model/Table/SubscriptionsTable.php:137

     */
    public function beforeMarshal(Event $event, ArrayObject $data, ArrayObject $options): void
    {
        $data['property'] = $this->getProperty();
        $data['property_id'] = $this->getPropertyId();
        $data['value'] = trim($data['value'] ?? '');
        $data['value'] = trim($data['value'], '\'"');
    }

    /**
     * @return \Cake\Datasource\EntityInterface|array
     * @throws \Passbolt\Subscription\Error\Exception\Subscriptions\SubscriptionRecordNotFoundException
     */
    public function getOrFail(): EntityInterface|array
    {
        try {
            return $this->find()->firstOrFail();
        } catch (Exception $e) {
            throw new SubscriptionRecordNotFoundException();
        }
    }

    /**
     * @inheritDoc
     */
    public function exists($conditions = []): bool
    {
        return parent::exists($conditions);
    }

    /**
     * @param string $asciiKey Subscription key string.
     * @param \App\Utility\UserAccessControl $uac Reporting who is acting.
     * @return string the key as original string
     */
    public function create(string $asciiKey, UserAccessControl $uac): string
    {

View on GitHub (pinned to 31c1bbc10f)