nextcloud/all-in-one · warning · \Exception
Could not register a free dedyn.io domain after {maxSlugAtte
Error message
Could not register a free dedyn.io domain after {maxSlugAttempts} attempts. Please try again. What it means
Random-slug mode tried MAX_SLUG_ATTEMPTS (5) times to register a randomly generated 10-hex-character <slug>.dedyn.io name and every attempt returned 409 (collision), because collisions are the only outcome that `continue`s the loop. The exception fires after the fifth consecutive collision.
Source
Thrown at php/src/Desec/DesecManager.php:331
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.');
}
/**
* Checks whether the authenticated account already owns the given domain.
*
* Used to recover from a failed creation when the user is reusing a slug they
* registered earlier: GET /domains/{name}/ returns 200 only for a domain the
* token's account owns, 404 otherwise.
*
* @throws \Exception on network failure or an unexpected HTTP response
*/
private function ownsDomain(string $token, string $domain): bool {
try {
$res = $this->guzzleClient->get($this->configurationManager->desecApiBase . '/domains/' . $domain . '/', [
'headers' => ['Authorization' => 'Token ' . $token],
]);
} catch (TransferException $e) {
throw new \Exception('Could not reach the deSEC API: ' . $e->getMessage());View on GitHub (pinned to 6b788eec5e)
Solutions
- Simply retry — fresh random slugs are drawn each run
- If it recurs, verify desecApiBase and that requests actually reach desec.io (a proxy answering 409 for everything would explain it)
- Fall back to a user-chosen unique slug to bypass random generation
Defensive patterns
Strategy: retry
Try / catch
try {
$domain = $manager->registerDomain($token, ''); // '' = random slug
} catch (\Exception $e) {
if (str_contains($e->getMessage(), 'Could not register a free dedyn.io domain after')) {
sleep(1);
return $manager->registerDomain($token, ''); // fresh random slugs next round
}
throw $e;
} Prevention
- Five consecutive 409s on random 10-hex-char names is an anomaly, not bad luck — verify the endpoint is really desec.io
- Always allow the empty-slug option in the UI so users can fall back to randomness
- Don't increase attempt counts without evidence; the math says collisions are ~impossible
When it happens
Trigger: Five consecutive 409s on random bin2hex(random_bytes(5)) names — each attempt retries with a fresh random slug, so reaching this requires astronomically bad luck or a deSEC-side anomaly that answers every POST /domains/ with 409.
Common situations: Practically never in normal operation; if seen, suspect the API is misbehaving (e.g. proxy or misrouted desecApiBase returning 409 for everything) rather than genuine collisions.
Related errors
- Your deSEC account has reached its domain limit and "{domain
- "{domain}" is already taken. Please choose a different subdo
- Unexpected response from deSEC during domain registration (H
- Unexpected response from deSEC while checking domain ownersh
- A domain is already configured. Reset the AIO instance first
AI-assisted analysis of nextcloud/all-in-one@6b788eec5e (2026-08-21).
Data as JSON: /api/errors/1ef7b85e65bb391e.
Report an issue: GitHub.