passbolt/passbolt_api · error · ForbiddenException

The self registration is disabled.

Error message

The self registration is disabled.

What it means

Thrown by SelfRegistrationEmailDomainsDryRunService::getAllowedDomainsInSettings when the stored self-registration settings exist but contain no allowed_domains data. Raised as ForbiddenException to signal that self-registration is effectively disabled for the instance. Prevents the domain check from running against a null allow-list.

Solutions

  1. Open Admin > Self Registration and configure at least one allowed domain, or POST valid settings with allowed_domains
  2. Verify the stored settings property data contains a non-null allowed_domains array
  3. Check that the email-domains dry-run service matches the configured provider type
  4. Re-save settings after any upgrade that changed their internal shape

Example fix

// before
// settings stored without domains
{"providers":{"emailDomains":{}}}
// after
{"providers":{"emailDomains":{"allowed_domains":["example.com","company.org"]}}}
Defensive patterns

Strategy: fallback

Validate before calling

const settings = await api.get('/self-registration/settings.json');
const domains = settings?.data?.allowed_domains;
if (!Array.isArray(domains) || domains.length === 0) {
  // self-registration effectively disabled — don't call dry-run
}

Type guard

const hasAllowedDomains = (s) => Array.isArray(s?.data?.allowed_domains) && s.data.allowed_domains.length > 0;

Try / catch

try {
    await api.post('/self-registration/dry-run', { email });
} catch (e) {
    if (e.status === 403 && /disabled/i.test(e.message)) { /* treat registration as closed */ }
}

Prevention

When it happens

Trigger: Dry-run when organization settings hold no 'allowed_domains' array (settings saved without domains, provider mismatch, or settings property absent entirely).

Common situations: Admin cleared the allowed domains list; settings stored under a different provider than the email-domains service reads; migration/version change altered the settings payload shape; fresh environment without configuration.

Understand the failure class

Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.

Related errors


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

Appendix: source

Thrown at plugins/PassboltCe/SelfRegistration/src/Service/DryRun/SelfRegistrationEmailDomainsDryRunService.php:65

        $email = $form->getData('email');
        $this->checkEmailDomainIsAllowed($email, $allowedDomains);
        $this->checkEmailNotPreviouslyRegistered($email);

        return true;
    }

    /**
     * @return array
     * @throws \Cake\Http\Exception\ForbiddenException if no allowed domains are found in the settings.
     * @throws \Cake\Http\Exception\InternalErrorException if the settings in DB are not valid.
     */
    protected function getAllowedDomainsInSettings(): array
    {
        // Fetch settings in DB
        $settings = $this->getSelfRegistrationSettingsInDB();
        $allowedDomains = $settings['data']['allowed_domains'] ?? null;
        if (is_null($allowedDomains)) {
            throw new ForbiddenException(__('The self registration is disabled.'));
        }

        return $allowedDomains;
    }

    /**
     * Check that the email complies to the allowed domains
     *
     * @param string $email Email to check
     * @param array $allowedDomains Allowed domains
     * @return void
     * @throws \App\Error\Exception\ValidationException if the email does not comply
     */
    protected function checkEmailDomainIsAllowed(string $email, array $allowedDomains): void
    {
        /** @var \App\Model\Table\UsersTable $UsersTable */
        $UsersTable = TableRegistry::getTableLocator()->get('Users');
        if (!$UsersTable->isUsernameCaseSensitive()) {

View on GitHub (pinned to 31c1bbc10f)