{"record":{"id":"6bed01b22e2332af","repo":"AlistGo/alist","slug":"error-occurred","errorCode":null,"errorMessage":"error occurred","messagePattern":"error occurred","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"server/handles/ssologin.go","lineNumber":401,"sourceCode":"\t\tcommon.ErrorResp(c, err, 400)\n\t\treturn\n\t}\n\tif platform == \"Dingtalk\" {\n\t\taccessToken := utils.Json.Get(resp.Body(), \"accessToken\").ToString()\n\t\tresp, err = ssoClient.R().SetHeader(\"x-acs-dingtalk-access-token\", accessToken).\n\t\t\tGet(userUrl)\n\t} else {\n\t\taccessToken := utils.Json.Get(resp.Body(), \"access_token\").ToString()\n\t\tresp, err = ssoClient.R().SetHeader(\"Authorization\", \"Bearer \"+accessToken).\n\t\t\tGet(userUrl)\n\t}\n\tif err != nil {\n\t\tcommon.ErrorResp(c, err, 400)\n\t\treturn\n\t}\n\tuserID := utils.Json.Get(resp.Body(), idField).ToString()\n\tif utils.SliceContains([]string{\"\", \"0\"}, userID) {\n\t\tcommon.ErrorResp(c, errors.New(\"error occurred\"), 400)\n\t\treturn\n\t}\n\tif argument == \"get_sso_id\" {\n\t\tif usecompatibility {\n\t\t\tc.Redirect(302, common.GetApiUrl(c.Request)+\"/@manage?sso_id=\"+userID)\n\t\t\treturn\n\t\t}\n\t\thtml := fmt.Sprintf(`<!DOCTYPE html>\n\t\t\t\t<head></head>\n\t\t\t\t<body>\n\t\t\t\t<script>\n\t\t\t\twindow.opener.postMessage({\"sso_id\": \"%s\"}, \"*\")\n\t\t\t\twindow.close()\n\t\t\t\t</script>\n\t\t\t\t</body>`, userID)\n\t\tc.Data(200, \"text/html; charset=utf-8\", []byte(html))\n\t\treturn\n\t}","sourceCodeStart":383,"sourceCodeEnd":419,"githubUrl":"https://github.com/AlistGo/alist/blob/843d9dc8149126976b2625911e45a4d3ffd6f2f5/server/handles/ssologin.go#L383-L419","documentation":"Returned by SSOLoginCallback after a successful HTTP call to the provider's user-info endpoint when the field configured as the user ID is absent from the response — utils.Json.Get returns '' and both '' and '0' are rejected. The generic 'error occurred' message (HTTP 400) masks the real cause: a platform field-mapping mismatch or a failed (but 2xx) token exchange returning an error body.","triggerScenarios":"The provider's userinfo JSON does not contain the configured id field (e.g. GitHub 'id' vs OIDC 'sub'); the access_token in the response body is empty because the token endpoint returned an OAuth error object, so the follow-up userinfo fetch returns an error payload without the id.","commonSituations":"Wrong 'platform' selected for the provider (custom platform with id field name mismatch); wrong client id/secret making the token endpoint return an error body; API rate-limiting or private-user restrictions on GitHub returning partial payloads; OAuth error JSON being silently parsed.","solutions":["Dump/inspect the provider's userinfo response with a real token and set the SSO settings' id field to the key that actually holds a stable non-zero id (e.g. 'id', 'sub', 'uid')","Verify client id/secret and callback URL — a failed token exchange yields an empty access_token and then this error","Confirm the selected platform matches the provider (Github/GitLab/OIDC/Dingtalk/Custom) since each pins different token/userinfo endpoints and field names"],"exampleFix":"// before: custom platform, user id field = \"uid\" but provider returns {\"id\": 42, ...}\n// after: set user id field to \"id\" in SSO settings","handlingStrategy":"try-catch","validationCode":"userID := utils.Json.Get(resp.Body(), idField).ToString()\nif slices.Contains([]string{\"\", \"0\"}, userID) {\n    // dump resp.Body() to logs: field mapping or token exchange is broken\n    log.Printf(\"sso userinfo missing %q: %s\", idField, resp.Body())\n}","typeGuard":null,"tryCatchPattern":"// Server-side: replace the generic message with actionable context\nuserID := utils.Json.Get(resp.Body(), idField).ToString()\nif slices.Contains([]string{\"\", \"0\"}, userID) {\n    return fmt.Errorf(\"sso userinfo response has no %q field (status %d): %s\", idField, resp.StatusCode(), resp.Body())\n}","preventionTips":["Smoke-test the whole SSO flow (token -> userinfo -> id claim) after any provider or setting change","Verify client id/secret and callback URL first — failed token exchanges masquerade as this error","Log the raw userinfo payload when the id field is missing; the generic 'error occurred' hides the cause"],"tags":["sso","oauth","http-api","field-mapping"],"backgroundTag":null,"analyzedSha":"843d9dc8149126976b2625911e45a4d3ffd6f2f5","analyzedAt":"2026-08-15T12:14:11.722Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}