nextcloud/all-in-one · error · \Exception

Your deSEC account has reached its domain limit and "{domain

Error message

Your deSEC account has reached its domain limit and "{domain}" is not one of your existing domains. Remove an unused domain at desec.io, or contact deSEC support to raise the limit, then try again.

What it means

POST /domains/ returned 403 — the deSEC account is at its domain quota — and the follow-up ownership check (GET /domains/{name}/ returning 404) confirmed the requested domain is NOT already owned by this account, so it cannot be reused as the 400/409 recovery path would allow.

Source

Thrown at php/src/Desec/DesecManager.php:314

            } catch (TransferException $e) {
                throw new \Exception('Could not reach the deSEC API: ' . $e->getMessage());
            }

            $code = $res->getStatusCode();

            if ($code === 201) {
                return $domain;
            }

            // For a user-specified slug, the name may be unavailable (400/409) or the account's
            // domain limit may be reached (403) precisely because the user already owns this
            // domain. Reuse it rather than failing.
            if (!$random && ($code === 400 || $code === 403 || $code === 409)) {
                if ($this->ownsDomain($token, $domain)) {
                    return $domain;
                }
                if ($code === 403) {
                    throw new \Exception(
                        'Your deSEC account has reached its domain limit and "' . $domain . '" is not '
                        . 'one of your existing domains. Remove an unused domain at desec.io, or contact '
                        . 'deSEC support to raise the limit, then try again.'
                    );
                }
                throw new \Exception('"' . $domain . '" is already taken. Please choose a different subdomain and try again.');
            }

            if ($code === 409) {
                // Random slug collided with an existing name — try another.
                continue;
            }

            throw new \Exception('Unexpected response from deSEC during domain registration (HTTP ' . $code . '): ' . $res->getBody()->getContents());
        }

        throw new \Exception('Could not register a free dedyn.io domain after ' . self::MAX_SLUG_ATTEMPTS . ' attempts. Please try again.');
    }

View on GitHub (pinned to 6b788eec5e)

Solutions

  1. Log in at desec.io and delete an unused domain from the account, then retry
  2. Contact deSEC support to raise the domain limit
  3. Reuse a slug you already own — the code detects and reuses owned domains automatically
  4. Use a fresh deSEC account/email if registering a separate instance is acceptable

Example fix

// before: create blindly and rely on the 403 error
$manager->registerDomain($token, $slug);
// after: check the account's domain list first and surface quota early
$owned = json_decode($guzzle->get("$apiBase/domains/", ['headers' => ['Authorization' => "Token $token"]])->getBody(), true);
if (count($owned) >= $domainLimit) {
    throw new \Exception('Domain limit reached: delete one domain at desec.io before continuing.');
}
$manager->registerDomain($token, $slug);
Defensive patterns

Strategy: validation

Validate before calling

// List owned domains and bail out BEFORE hitting the quota
$res = $guzzle->get("$apiBase/domains/", ['headers' => ['Authorization' => "Token $token"]]);
$owned = json_decode($res->getBody()->getContents(), true) ?: [];
if (count($owned) >= DOMAIN_LIMIT) {
    throw new \Exception('At deSEC domain limit (' . DOMAIN_LIMIT . '). Remove a domain at desec.io first.');
}

Try / catch

try {
    $domain = $manager->registerDomain($token, $slug);
} catch (\Exception $e) {
    if (str_contains($e->getMessage(), 'reached its domain limit')) {
        renderQuotaHelp($e->getMessage()); // link to desec.io domain management
        return;
    }
    throw $e;
}

Prevention

When it happens

Trigger: User-specified slug, POST /domains/ → 403 (limit reached), then ownsDomain() → 404 (not yours): the quota is exhausted and this exact domain is unavailable for reuse.

Common situations: User registered several dedyn.io domains in earlier attempts and hit the free-account cap; default deSEC domain limit reached before finishing AIO setup.

Related errors


AI-assisted analysis of nextcloud/all-in-one@6b788eec5e (2026-08-21). Data as JSON: /api/errors/d621933b3b87bbac. Report an issue: GitHub.