{"record":{"id":"3d9bcf592798fd6a","repo":"nextcloud/all-in-one","slug":"unexpected-response-from-desec-during-login-http","errorCode":null,"errorMessage":"Unexpected response from deSEC during login (HTTP {code}): {body}","messagePattern":"Unexpected response from deSEC during login \\(HTTP (.+?)\\): (.+?)","errorType":"exception","errorClass":"\\Exception","httpStatus":422,"severity":"error","filePath":"php/src/Desec/DesecManager.php","lineNumber":258,"sourceCode":"     */\n    public function loginAccount(string $email, string $password): string {\n        try {\n            $res = $this->guzzleClient->post($this->configurationManager->desecApiBase . '/auth/login/', [\n                'json' => ['email' => $email, 'password' => $password],\n            ]);\n        } catch (TransferException $e) {\n            throw new \\Exception('Could not reach the deSEC API: ' . $e->getMessage());\n        }\n\n        $code = $res->getStatusCode();\n        $body = $res->getBody()->getContents();\n\n        if ($code === 400 || $code === 403) {\n            throw new \\Exception('Could not log in to deSEC: invalid email address or password.');\n        }\n\n        if ($code !== 200 && $code !== 201) {\n            throw new \\Exception('Unexpected response from deSEC during login (HTTP ' . $code . '): ' . $body);\n        }\n\n        $data = json_decode($body, true, 512, JSON_THROW_ON_ERROR);\n        if (!is_array($data) || !isset($data['token']) || !is_string($data['token'])) {\n            throw new \\Exception('Could not extract the API token from the deSEC login response. Please try again.');\n        }\n\n        return $data['token'];\n    }\n\n    /**\n     * Registers a dedyn.io domain for the authenticated account.\n     * When $slug is empty a random 10-character slug is tried up to MAX_SLUG_ATTEMPTS times.\n     *\n     * When a specific slug is requested and creation fails because the name is unavailable\n     * (HTTP 400/409) or the account's domain limit is reached (HTTP 403), the domain may\n     * already belong to this very account — a user reusing a slug they registered earlier.\n     * In that case we reuse the existing domain instead of failing, so an existing-account","sourceCodeStart":240,"sourceCodeEnd":276,"githubUrl":"https://github.com/nextcloud/all-in-one/blob/6b788eec5e61733cf03ed380a3572e43ae3f11ce/php/src/Desec/DesecManager.php#L240-L276","documentation":"POST /auth/login/ returned a status other than the accepted 200/201 (and other than the 400/403 invalid-credentials case), so the manager surfaces the unexpected status code plus the raw body. Transport errors cannot produce this — they are caught earlier as 'Could not reach the deSEC API'.","triggerScenarios":"deSEC returns 429 (login rate limit), 401, 5xx, or an intermediate proxy answers with its own status; any code outside {200, 201, 400, 403}.","commonSituations":"Repeated login retries hitting deSEC rate limiting; desec.io incident returning 502/503; an intercepting proxy or captive portal responding instead of the API.","solutions":["Read the embedded body — it carries the daemon/API's own error text","On 429, wait before retrying instead of looping immediately","On 5xx, check deSEC service status and retry later","If a proxy is in path, bypass it for desec.io or configure it correctly"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    $token = $manager->loginAccount($email, $password);\n} catch (\\Exception $e) {\n    if (preg_match('/Unexpected response from deSEC during login \\(HTTP (\\d+)\\)/', $e->getMessage(), $m)) {\n        [$code, $body] = [$m[1], substr($e->getMessage(), strpos($e->getMessage(), '): ') + 3)];\n        if ($code === '429') { scheduleRetry(60); return; }\n        logError(\"deSEC login anomaly HTTP $code: $body\");\n    }\n    throw $e;\n}","preventionTips":["Rate-limit your own login attempts so deSEC's 429 is never triggered","Log the full body on unexpected statuses — it is the only place the API explains itself","Monitor deSEC API changelog for status-code contract changes"],"tags":["php","desec","http-status","login"],"backgroundTag":"unexpected-http-status","analyzedSha":"6b788eec5e61733cf03ed380a3572e43ae3f11ce","analyzedAt":"2026-08-21T05:47:24.382Z","schemaVersion":2},"datasetVersion":"2026-08-21T11:28:35.574Z"}