{"record":{"id":"6468238b6b1495ab","repo":"plandex-ai/plandex","slug":"token-exchange-failed-error-creating-request-s","errorCode":null,"errorMessage":"token exchange failed - error creating request: %s","messagePattern":"token exchange failed - error creating request: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/cli/lib/claude_max.go","lineNumber":242,"sourceCode":"\t\t},\n\t}\n\tif err := SetAccountCredentials(&creds); err != nil {\n\t\tterm.OutputErrorAndExit(\"Error setting account credentials: %v\", err)\n\t}\n}\n\nfunc exchangeCode(code, verifier, state string) (*types.OauthResponse, error) {\n\tbody, _ := json.Marshal(map[string]any{\n\t\t\"grant_type\":    \"authorization_code\",\n\t\t\"code\":          code,\n\t\t\"state\":         state,\n\t\t\"code_verifier\": verifier,\n\t\t\"redirect_uri\":  claudeMaxRedirect,\n\t\t\"client_id\":     claudeMaxClientId,\n\t})\n\treq, err := http.NewRequest(\"POST\", claudeMaxTokenUrl, bytes.NewReader(body))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"token exchange failed - error creating request: %s\", err)\n\t}\n\n\treq.Header.Set(\"Content-Type\", \"application/json\")\n\treq.Header.Set(\"anthropic-beta\", shared.AnthropicClaudeMaxBetaHeader)\n\n\tresp, err := http.DefaultClient.Do(req)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tdefer resp.Body.Close()\n\tif resp.StatusCode != http.StatusOK {\n\t\tb, err := io.ReadAll(resp.Body)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"token exchange failed - error reading body: %s\", err)\n\t\t}\n\t\treturn nil, fmt.Errorf(\"token exchange failed - status: %d, body: %s\", resp.StatusCode, b)\n\t}\n\tvar t types.OauthResponse","sourceCodeStart":224,"sourceCodeEnd":260,"githubUrl":"https://github.com/plandex-ai/plandex/blob/e2d772072efadbe41d2946d97d79be55532dbab5/app/cli/lib/claude_max.go#L224-L260","documentation":"In the Claude Max OAuth flow, exchangeCode() performs the authorization-code-to-token exchange against claudeMaxTokenUrl. This error is returned when http.NewRequest fails to even construct the POST request — before any network I/O happens. It wraps the http.NewRequest error.","triggerScenarios":"http.NewRequest(\"POST\", claudeMaxTokenUrl, bytes.NewReader(body)) returns an error — almost always because the URL constant is malformed (unparseable URL) since body is a valid bytes.Reader.","commonSituations":"A bad build-time constant or environment override corrupted claudeMaxTokenUrl (e.g. empty string, invalid characters, missing scheme); misconfigured proxy environment variables feeding into a customized URL.","solutions":["Inspect the wrapped error; it names the URL parse failure.","Verify claudeMaxTokenUrl is a valid absolute https URL (non-empty, with scheme).","Check that no config/env override mangles the token endpoint value.","Rebuild with the correct upstream URL constant."],"exampleFix":"// before\nreq, err := http.NewRequest(\"POST\", claudeMaxTokenUrl, bytes.NewReader(body))\n// after\nreq, err := http.NewRequest(\"POST\", claudeMaxTokenUrl, bytes.NewReader(body))\nif err != nil {\n\treturn nil, fmt.Errorf(\"token exchange failed - invalid token url %q: %w\", claudeMaxTokenUrl, err)\n}","handlingStrategy":"validation","validationCode":"func validURL(s string) bool {\n\tu, err := url.Parse(s)\n\treturn err == nil && (u.Scheme == \"https\" || u.Scheme == \"http\") && u.Host != \"\"\n}\nif !validURL(claudeMaxTokenUrl) { /* fail fast before exchange */ }","typeGuard":"func isRequestCreationErr(err error) bool { return strings.Contains(err.Error(), \"error creating request\") }","tryCatchPattern":"tok, err := exchangeCode(ctx, code, verifier)\nif err != nil {\n\tif strings.Contains(err.Error(), \"error creating request\") {\n\t\t// bad URL constant/config: no point retrying, fix config\n\t}\n}","preventionTips":["Keep token endpoint URLs as compile-time constants, not user input.","Validate URL scheme/host before constructing requests.","Don't allow env overrides to blank or corrupt the token URL.","Add a startup sanity check of all OAuth endpoint URLs."],"tags":["go","oauth","http","token-exchange"],"backgroundTag":"oauth-token-exchange-failed","analyzedSha":"e2d772072efadbe41d2946d97d79be55532dbab5","analyzedAt":"2026-09-05T20:56:53.631Z","contentChangedAt":"2026-09-05T20:56:53.631Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}