{"record":{"id":"7c82b6c5d08d358b","repo":"infiniflow/ragflow","slug":"login-failed-invalid-json-response-exc","errorCode":null,"errorMessage":"Login failed: invalid JSON response ({exc})","messagePattern":"Login failed: invalid JSON response \\((.+?)\\)","errorType":"exception","errorClass":"AuthException","httpStatus":401,"severity":"error","filePath":"admin/client/user.py","lineNumber":70,"sourceCode":"    if res.get(\"code\") == 0:\n        return\n    msg = res.get(\"message\", \"\")\n    if \"has already registered\" in msg:\n        return\n    raise AuthException(f\"Register failed: {msg}\")\n\n\ndef login_user(client: HttpClient, server_type: str, email: str, password: str) -> str:\n    password_enc = encrypt_password(password)\n    payload = {\"email\": email, \"password\": password_enc}\n    if server_type == \"admin\":\n        response = client.request(\"POST\", \"/admin/login\", use_api_base=True, auth_kind=None, json_body=payload)\n    else:\n        response = client.request(\"POST\", \"/auth/login\", use_api_base=True, auth_kind=None, json_body=payload)\n    try:\n        res = response.json()\n    except Exception as exc:\n        raise AuthException(f\"Login failed: invalid JSON response ({exc})\") from exc\n    if res.get(\"code\") != 0:\n        raise AuthException(f\"Login failed: {res.get('message')}\")\n    token = response.headers.get(\"Authorization\")\n    if not token:\n        raise AuthException(\"Login failed: missing Authorization header\")\n    return token\n","sourceCodeStart":52,"sourceCodeEnd":77,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/admin/client/user.py#L52-L77","documentation":"Raised by login_user when response.json() fails on the login response (POST /admin/login or /auth/login). The auth endpoint returned a non-JSON body — typically an HTML error page from a gateway, a plain-text 502/504, or an empty body — so the client cannot extract code/message. The original parse exception is chained.","triggerScenarios":"The login POST hits a reverse proxy returning an HTML 502/504 page; the server crashed mid-request returning an empty body; the URL points to a static site or wrong port; a redirect (302 to a login HTML page) followed by axios/requests returning HTML.","commonSituations":"Docker compose services not fully up when the admin script runs; nginx misrouting /auth/login; wrong port in the client's base URL; TLS termination returning an error page.","solutions":["curl -i the login endpoint directly to see the raw non-JSON body and its status","Verify the server is up and the API base URL/port in the client config is correct","If a proxy is involved, check its error page configuration and upstream health","Wait for services to be healthy before running the admin client (e.g. depends_on/healthcheck in compose)"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"import json\n\ndef is_json_login_response(text: str) -> bool:\n    try:\n        parsed = json.loads(text)\n    except ValueError:\n        return False\n    return isinstance(parsed, dict) and \"code\" in parsed\n\n# probe the endpoint before the full flow:\nresp = client.request(\"GET\", \"/\")\nif resp.headers.get(\"content-type\", \"\").startswith(\"text/html\"):\n    raise RuntimeError(\"API base URL returns HTML — check server/proxy config\")","typeGuard":"def is_json_body(response) -> bool:\n    content_type = response.headers.get(\"content-type\", \"\")\n    return \"application/json\" in content_type","tryCatchPattern":"try:\n    res = response.json()\nexcept Exception as exc:\n    raise AuthException(\n        f\"Login failed: non-JSON response (status={response.status_code}, \"\n        f\"content-type={response.headers.get('content-type', 'unknown')})\"\n    ) from exc","preventionTips":["Health-check the API base URL (expect JSON content-type) before running auth flows","Ensure all backend services are up (compose healthchecks) before invoking the admin client","Check reverse-proxy routing so /auth/login and /admin/login reach the app, not an error page"],"tags":["auth","login","json","proxy","python","network"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}