nextcloud/all-in-one · error · \Exception
Unexpected response from deSEC while checking domain ownersh
Error message
Unexpected response from deSEC while checking domain ownership (HTTP {code}): {body} What it means
GET {desecApiBase}/domains/{domain}/ returned a status other than 200 (owned) or 404 (not owned) during the ownership check. Realistic codes: 401 (token expired or revoked between calls), 429 (rate limit), 5xx (deSEC incident). The raw body is embedded.
Source
Thrown at php/src/Desec/DesecManager.php:362
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());
}
$code = $res->getStatusCode();
if ($code === 200) {
return true;
}
if ($code === 404) {
return false;
}
throw new \Exception('Unexpected response from deSEC while checking domain ownership (HTTP ' . $code . '): ' . $res->getBody()->getContents());
}
/**
* Creates a wildcard CNAME rrset (*.domain → domain.) for a newly registered domain.
* Errors are logged but do not abort the overall registration.
*/
private function createWildcardCname(string $token, string $domain): void {
try {
$res = $this->guzzleClient->post($this->configurationManager->desecApiBase . '/domains/' . $domain . '/rrsets/', [
'headers' => ['Authorization' => 'Token ' . $token],
'json' => [
'subname' => '*',
'type' => 'CNAME',
'ttl' => 3600,
'records' => [$domain . '.'],
],
]);
} catch (TransferException $e) {View on GitHub (pinned to 6b788eec5e)
Solutions
- On 401, re-authenticate with loginAccount() to mint a fresh token and restart the flow
- On 429, back off and retry the ownership check
- Read the embedded body for the exact API message
- Confirm the account password was not reset at desec.io mid-flow
Defensive patterns
Strategy: try-catch
Validate before calling
// Verify the token is still live before the ownership-sensitive flow
$res = $guzzle->get("$apiBase/domains/", ['headers' => ['Authorization' => "Token $token"], 'http_errors' => false]);
if ($res->getStatusCode() === 401) {
$token = $manager->loginAccount($email, $password); // mint a fresh token
} Try / catch
try {
$manager->registerDomain($token, $slug);
} catch (\Exception $e) {
if (str_contains($e->getMessage(), 'checking domain ownership')) {
if (str_contains($e->getMessage(), '(HTTP 401)')) { $token = relogin(); return retry(); }
if (str_contains($e->getMessage(), '(HTTP 429)')) { scheduleRetry(30); return; }
}
throw $e;
} Prevention
- Don't hold deSEC tokens across long waits — re-login before retrying a multi-step flow
- Remember a desec.io password reset revokes existing tokens
- Treat 401 on this GET as a token-liveness signal, not a domain fact
When it happens
Trigger: The bearer token became invalid between the failed POST /domains/ and this GET (e.g. user reset the deSEC password, which revokes tokens); 429 or 5xx from the API.
Common situations: Long-lived token invalidated by a password change on desec.io; rate limiting after repeated attempts; desec.io instability.
Related errors
- Unexpected response from deSEC during domain registration (H
- Unexpected response from deSEC during account registration (
- Unexpected response from deSEC during login (HTTP {code}): {
- Your deSEC account has reached its domain limit and "{domain
- "{domain}" is already taken. Please choose a different subdo
AI-assisted analysis of nextcloud/all-in-one@6b788eec5e (2026-08-21).
Data as JSON: /api/errors/42d90a8ea62c5124.
Report an issue: GitHub.