{"record":{"id":"12833cb4d2a37944","repo":"sipeed/picoclaw","slug":"error-fetching-models-w","errorCode":null,"errorMessage":"error fetching models: %w","messagePattern":"error fetching models: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/picoclaw/internal/auth/helpers.go","lineNumber":463,"sourceCode":"\tif cred.NeedsRefresh() && cred.RefreshToken != \"\" {\n\t\toauthCfg := auth.GoogleAntigravityOAuthConfig()\n\t\trefreshed, refreshErr := auth.RefreshAccessToken(cred, oauthCfg)\n\t\tif refreshErr == nil {\n\t\t\tcred = refreshed\n\t\t\t_ = auth.SetCredential(\"google-antigravity\", cred)\n\t\t}\n\t}\n\n\tprojectID := cred.ProjectID\n\tif projectID == \"\" {\n\t\treturn fmt.Errorf(\"no project id stored. Try logging in again\")\n\t}\n\n\tfmt.Printf(\"Fetching models for project: %s\\n\\n\", projectID)\n\n\tmodels, err := providers.FetchAntigravityModels(cred.AccessToken, projectID)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error fetching models: %w\", err)\n\t}\n\n\tif len(models) == 0 {\n\t\treturn fmt.Errorf(\"no models available\")\n\t}\n\n\tfmt.Println(\"Available Antigravity Models:\")\n\tfmt.Println(\"-----------------------------\")\n\tfor _, m := range models {\n\t\tstatus := \"✓\"\n\t\tif m.IsExhausted {\n\t\t\tstatus = \"✗ (quota exhausted)\"\n\t\t}\n\t\tname := m.ID\n\t\tif m.DisplayName != \"\" {\n\t\t\tname = fmt.Sprintf(\"%s (%s)\", m.ID, m.DisplayName)\n\t\t}\n\t\tfmt.Printf(\"  %s %s\\n\", status, name)","sourceCodeStart":445,"sourceCodeEnd":481,"githubUrl":"https://github.com/sipeed/picoclaw/blob/49183d7e8daed0dba89ddbb6fcb60089401d9680/cmd/picoclaw/internal/auth/helpers.go#L445-L481","documentation":"Wrapped error from providers.FetchAntigravityModels, which POSTs to the Antigravity Cloud Code Assist endpoint /v1internal:fetchAvailableModels with the stored OAuth Bearer token and a 15s HTTP timeout (pkg/providers/oauth/antigravity_provider.go:554). The underlying error can be a transport failure, a non-200 response such as 'fetchAvailableModels failed (HTTP 401)' for an expired token or HTTP 429 for quota, or a JSON parse error on the response body. The %w preserves the cause for errors.Is/As inspection.","triggerScenarios":"Running the models-listing auth helper with a stale/revoked Antigravity access token (HTTP 401/403); hitting the API quota (HTTP 429 'rate limit exceeded'); network offline or DNS failure; API endpoint/UA header change making the server return HTML instead of JSON; slow network exceeding the hardcoded 15s http.Client timeout.","commonSituations":"User logged in days ago and the token expired, then runs the models command; corporate proxy blocks googleapis domains; quota window exhausted after heavy use; picoclaw version lagging an upstream Antigravity API contract change.","solutions":["Re-login with the Antigravity auth command to refresh the access token, then retry","Read the wrapped cause: HTTP 401/403 means token, HTTP 429 means wait for the reported quotaResetDelay, JSON/parse text means API contract change","Check network/proxy connectivity to the Antigravity API host","If HTTP 429, wait for the quota reset time shown in the message before retrying","Update picoclaw to the latest version in case the fetchAvailableModels endpoint or required headers changed"],"exampleFix":"// before\nmodels, err := providers.FetchAntigravityModels(cred.AccessToken, projectID)\nif err != nil {\n\treturn fmt.Errorf(\"error fetching models: %w\", err)\n}\n\n// after: surface an actionable hint for the common auth cause\nmodels, err := providers.FetchAntigravityModels(cred.AccessToken, projectID)\nif err != nil {\n\tif strings.Contains(err.Error(), \"HTTP 401\") || strings.Contains(err.Error(), \"HTTP 403\") {\n\t\treturn fmt.Errorf(\"error fetching models (token may be expired, try logging in again): %w\", err)\n\t}\n\treturn fmt.Errorf(\"error fetching models: %w\", err)\n}","handlingStrategy":"try-catch","validationCode":"// Verify credentials exist and look fresh before calling\nif cred.AccessToken == \"\" {\n\treturn errors.New(\"not logged in: run the antigravity login command first\")\n}","typeGuard":"func isAuthFailure(err error) bool {\n\tif err == nil {\n\t\treturn false\n\t}\n\tmsg := err.Error()\n\treturn strings.Contains(msg, \"HTTP 401\") || strings.Contains(msg, \"HTTP 403\")\n}","tryCatchPattern":"models, err := providers.FetchAntigravityModels(cred.AccessToken, projectID)\nif err != nil {\n\tif isAuthFailure(err) {\n\t\t// re-login flow, then retry once\n\t} else if strings.Contains(err.Error(), \"HTTP 429\") {\n\t\t// backoff until the reported quotaResetDelay elapses\n\t} else {\n\t\treturn fmt.Errorf(\"error fetching models: %w\", err)\n\t}\n}","preventionTips":["Refresh the Antigravity token on 401/403 before any retry","Cache model listings briefly instead of fetching on every invocation to avoid 429s","Wrap the call with a net/http client timeout larger than the 15s default when on slow links"],"tags":["go","antigravity","oauth","network","api"],"backgroundTag":null,"analyzedSha":"49183d7e8daed0dba89ddbb6fcb60089401d9680","analyzedAt":"2026-08-15T21:55:41.315Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}