{"record":{"id":"103790d89a6cb14b","repo":"router-for-me/CLIProxyAPI","slug":"xai-device-code-response-missing-user-code","errorCode":null,"errorMessage":"xai device code: response missing user_code","messagePattern":"xai device code: response missing user_code","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/auth/xai/xai.go","lineNumber":169,"sourceCode":"\t}()\n\n\tbody, err := io.ReadAll(resp.Body)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"xai device code: read response: %w\", err)\n\t}\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"xai device code request failed with status %d: %s\", resp.StatusCode, strings.TrimSpace(string(body)))\n\t}\n\n\tvar deviceCode DeviceCodeResponse\n\tif err = json.Unmarshal(body, &deviceCode); err != nil {\n\t\treturn nil, fmt.Errorf(\"xai device code: parse response: %w\", err)\n\t}\n\tif strings.TrimSpace(deviceCode.DeviceCode) == \"\" {\n\t\treturn nil, fmt.Errorf(\"xai device code: response missing device_code\")\n\t}\n\tif strings.TrimSpace(deviceCode.UserCode) == \"\" {\n\t\treturn nil, fmt.Errorf(\"xai device code: response missing user_code\")\n\t}\n\tif strings.TrimSpace(deviceCode.VerificationURI) == \"\" && strings.TrimSpace(deviceCode.VerificationURIComplete) == \"\" {\n\t\treturn nil, fmt.Errorf(\"xai device code: response missing verification URI\")\n\t}\n\tdeviceCode.TokenEndpoint = strings.TrimSpace(tokenEndpoint)\n\treturn &deviceCode, nil\n}\n\n// WaitForAuthorization polls until the user authorizes the device code and returns tokens.\nfunc (a *XAIAuth) WaitForAuthorization(ctx context.Context, deviceCode *DeviceCodeResponse) (*AuthBundle, error) {\n\ttokenData, err := a.PollForToken(ctx, deviceCode)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\ttokenEndpoint := \"\"\n\tif deviceCode != nil {\n\t\ttokenEndpoint = strings.TrimSpace(deviceCode.TokenEndpoint)\n\t}","sourceCodeStart":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/router-for-me/CLIProxyAPI/blob/78f0c4079e3e6273d65d03b5549cffc898703264/internal/auth/xai/xai.go#L151-L187","documentation":"The device authorization response parsed correctly and contained a device_code, but user_code is empty. user_code is the short string the user must type at the verification URI; without it the interactive authorization step is impossible, so the client refuses to proceed.","triggerScenarios":"POST to the xAI device authorization endpoint returns 200 JSON with device_code present but user_code absent or whitespace-only.","commonSituations":"Partial or evolving server response schema from xAI; a middleware/proxy stripping fields; a misconfigured client_id that yields a degraded response instead of a 4xx error.","solutions":["Log the raw body alongside the error to see the full server payload","Verify the request is going to the official xAI device authorization endpoint via a.Discover","Check whether xAI renamed user_code (e.g. to a nested field) and update the DeviceCodeResponse struct if so"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":"deviceCode, err := auth.RequestDeviceCode(ctx)\nif err != nil {\n    if strings.Contains(err.Error(), \"response missing\") {\n        // server contract issue: log raw context and surface to the user\n        log.Warnf(\"xAI device authorization response incomplete: %v\", err)\n    }\n    return err\n}","preventionTips":["Log the raw authorization response body during development to catch schema drift early","Contract-test the device authorization response fields when upgrading the library"],"tags":["oauth","device-flow","xai","auth","response-validation"],"backgroundTag":null,"analyzedSha":"78f0c4079e3e6273d65d03b5549cffc898703264","analyzedAt":"2026-08-15T12:26:37.444Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}