{"record":{"id":"50b4cbad3f8e63e3","repo":"weaviate/weaviate","slug":"failed-to-decode-auth-broker-response-w-50b4cb","errorCode":null,"errorMessage":"failed to decode auth broker response: %w","messagePattern":"failed to decode auth broker response: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"usecases/modulecomponents/gcpcommon/auth_broker.go","lineNumber":140,"sourceCode":"\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"%w: %w\", ErrRetryableAuthBroker, err)\n\t}\n\tdefer func() {\n\t\t_, _ = io.Copy(io.Discard, resp.Body)\n\t\tresp.Body.Close()\n\t}()\n\n\tif resp.StatusCode >= 500 || resp.StatusCode == http.StatusTooManyRequests {\n\t\treturn nil, fmt.Errorf(\"%w: auth broker returned status %d\", ErrRetryableAuthBroker, resp.StatusCode)\n\t}\n\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"auth broker returned non-200 status: %d\", resp.StatusCode)\n\t}\n\n\tvar bt AuthBrokerToken\n\tif err := json.NewDecoder(resp.Body).Decode(&bt); err != nil {\n\t\treturn nil, fmt.Errorf(\"failed to decode auth broker response: %w\", err)\n\t}\n\n\tif bt.AccessToken == \"\" || bt.Expiry.IsZero() {\n\t\treturn nil, errors.New(\"auth broker response missing required fields (access_token, expiry)\")\n\t}\n\n\treturn &oauth2.Token{\n\t\tAccessToken: bt.AccessToken,\n\t\tTokenType:   bt.TokenType,\n\t\tExpiry:      bt.Expiry,\n\t}, nil\n}\n\nfunc (b *AuthBrokerTokenSource) getIdentityToken(ctx context.Context) (string, error) {\n\tif !metadata.OnGCE() {\n\t\treturn \"\", errors.New(\"cluster is not running on GCE/GKE\")\n\t}\n","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/weaviate/weaviate/blob/75aa4b6d11f8818305aafd4440b4e32794f7ca04/usecases/modulecomponents/gcpcommon/auth_broker.go#L122-L158","documentation":"Thrown by fetchToken when the auth broker returned HTTP 200 but the response body could not be parsed as JSON into AuthBrokerToken. This indicates the endpoint did not return the expected {access_token, expiry, token_type} payload — typically because the URL points at an HTML page, a proxy login page, or an error body that still carries status 200.","triggerScenarios":"Token() → fetchTokenWithRetry → fetchToken, when json.NewDecoder(resp.Body).Decode fails: malformed JSON, empty body, HTML content, or a truncated response from the broker.","commonSituations":"Typo in auth-broker URL hitting a landing page; a corporate proxy or load balancer injecting an HTML error/interstitial page; broker service returning an empty body on 200; TLS-terminating middleware rewriting the response.","solutions":["Curl the auth-broker endpoint with a valid identity token and inspect the raw response body","Ensure the endpoint URL points at the JSON token API, not a UI or redirect page","Check proxies/load balancers between Weaviate and the broker for body rewriting","Update Weaviate/broker if the token JSON schema changed"],"exampleFix":"// before: endpoint pointing at UI page\n\"authEndpoint\": \"https://auth-broker.example.com/\"\n// after: endpoint pointing at JSON token API\n\"authEndpoint\": \"https://auth-broker.example.com/v1/token\"","handlingStrategy":"try-catch","validationCode":"// Go: assert the endpoint returns valid JSON before use\nresp, _ := http.Get(brokerEndpoint)\nbody, _ := io.ReadAll(resp.Body)\nvar probe map[string]any\nif json.Unmarshal(body, &probe) != nil {\n    return errors.New(\"broker endpoint does not return JSON\")\n}","typeGuard":null,"tryCatchPattern":"if err != nil {\n    if strings.Contains(err.Error(), \"failed to decode auth broker response\") {\n        // log response content-type/body shape; endpoint likely wrong or proxied\n        return fmt.Errorf(\"broker returned non-JSON payload, check endpoint: %w\", err)\n    }\n    return err\n}","preventionTips":["Curl the endpoint once at deploy time and confirm JSON with access_token/expiry","Bypass or audit proxies that may inject HTML interstitials","Pin the broker URL to the JSON API path, not the base URL"],"tags":["gcp","json","auth-broker","decode"],"backgroundTag":"invalid-json-response","analyzedSha":"75aa4b6d11f8818305aafd4440b4e32794f7ca04","analyzedAt":"2026-09-04T14:58:20.392Z","contentChangedAt":"2026-09-04T14:58:20.392Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}