{"record":{"id":"9371679d63cf7151","repo":"sipeed/picoclaw","slug":"could-not-find-authorization-code-in-input","errorCode":null,"errorMessage":"could not find authorization code in input","messagePattern":"could not find authorization code in input","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"pkg/auth/oauth.go","lineNumber":179,"sourceCode":"\tcase result := <-resultCh:\n\t\tif result.err != nil {\n\t\t\treturn nil, result.err\n\t\t}\n\t\treturn ExchangeCodeForTokens(cfg, result.code, pkce.CodeVerifier, redirectURI)\n\tcase manualInput := <-manualCh:\n\t\tif manualInput == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"manual input canceled\")\n\t\t}\n\t\t// Extract code from URL if it's a full URL\n\t\tcode := manualInput\n\t\tif strings.Contains(manualInput, \"?\") {\n\t\t\tu, err := url.Parse(manualInput)\n\t\t\tif err == nil {\n\t\t\t\tcode = u.Query().Get(\"code\")\n\t\t\t}\n\t\t}\n\t\tif code == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"could not find authorization code in input\")\n\t\t}\n\t\treturn ExchangeCodeForTokens(cfg, code, pkce.CodeVerifier, redirectURI)\n\tcase <-time.After(5 * time.Minute):\n\t\treturn nil, fmt.Errorf(\"authentication timed out after 5 minutes\")\n\t}\n}\n\nfunc oauthCallbackRedirectURI(port int) string {\n\treturn fmt.Sprintf(\"http://localhost:%d/auth/callback\", port)\n}\n\nfunc oauthCallbackHandler(state string, resultCh chan<- callbackResult) http.Handler {\n\tmux := http.NewServeMux()\n\tmux.HandleFunc(\"/auth/callback\", func(w http.ResponseWriter, r *http.Request) {\n\t\tif r.URL.Query().Get(\"state\") != state {\n\t\t\tresultCh <- callbackResult{err: fmt.Errorf(\"state mismatch\")}\n\t\t\thttp.Error(w, \"State mismatch\", http.StatusBadRequest)\n\t\t\treturn","sourceCodeStart":161,"sourceCodeEnd":197,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/pkg/auth/oauth.go#L161-L197","documentation":"The manual input was non-empty but contained no authorization code (oauth.go:179): it had no '?' (so it was treated as a raw code but was blank-ish) or url.Parse found no code query parameter. The user pasted the wrong URL — typically the verification/consent page instead of the post-login localhost redirect.","triggerScenarios":"Pasting the authorization URL (the one printed for the browser) instead of the resulting redirect; pasting a redirect URL where the provider appended only state and error (denied consent); trailing whitespace/newline making the code extraction fail; pasting a URL whose fragment (#code=) rather than query (?code=) carries the code.","commonSituations":"First-time users confusing 'open this URL' with 'paste the URL you land on'; providers that redirect with code in the fragment; copy including surrounding log text so '?' branch parses the wrong URL.","solutions":["After granting access in the browser, copy the entire address of the final localhost/auth/callback?... page — it must contain ?code=","If the browser shows 'connection refused' on localhost, that page's URL is still the one to paste","Alternatively paste just the bare code value if your provider shows one","Retry the login flow; the code is single-use and short-lived anyway"],"exampleFix":"// before: paste the authorization URL\n// https://accounts.example.com/o/oauth2/v2/auth?client_id=...&state=...\n\n// after: paste the post-consent redirect URL\n// http://localhost:51121/auth/callback?state=...&code=4/0Ax4Xb...  <- this one","handlingStrategy":"validation","validationCode":"// validate manual input before submitting to the flow\nfunc extractCode(input string) (string, error) {\n    input = strings.TrimSpace(input)\n    if input == \"\" { return \"\", fmt.Errorf(\"empty input\") }\n    if strings.Contains(input, \"?\") {\n        if u, err := url.Parse(input); err == nil {\n            if c := u.Query().Get(\"code\"); c != \"\" { return c, nil }\n        }\n        return \"\", fmt.Errorf(\"URL has no code= parameter; paste the localhost redirect URL\")\n    }\n    return input, nil // assume bare code\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"could not find authorization code\") {\n    fmt.Println(\"pasted value lacked ?code= — copy the final http://localhost.../auth/callback?... URL and retry\")\n    return err\n}","preventionTips":["Check input contains 'code=' before submitting","Paste the post-consent localhost redirect URL, not the authorization URL","Prefer the automatic browser callback over manual paste when possible"],"tags":["oauth","user-input","parsing","login"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}