{"record":{"id":"9147bba52d3a36b4","repo":"ory/hydra","slug":"expected-status-code-200-but-got-d-when-requestin","errorCode":null,"errorMessage":"expected status code 200 but got %d when requesting %s","messagePattern":"expected status code 200 but got (.+?) when requesting (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"oryx/jwksx/fetcher.go","lineNumber":53,"sourceCode":"\n// GetKey retrieves a JSON Web Key from the cache, fetches it from a remote if it is not yet cached or returns an error.\n//\n// DEPRECATED: Use FetcherNext instead.\nfunc (f *Fetcher) GetKey(kid string) (*jose.JSONWebKey, error) {\n\tf.RLock()\n\tif k, ok := f.keys[kid]; ok {\n\t\tf.RUnlock()\n\t\treturn &k, nil\n\t}\n\tf.RUnlock()\n\n\tres, err := f.c.Get(f.remote)\n\tif err != nil {\n\t\treturn nil, errors.WithStack(err)\n\t}\n\tdefer res.Body.Close()\n\tif res.StatusCode != http.StatusOK {\n\t\treturn nil, errors.Errorf(\"expected status code 200 but got %d when requesting %s\", res.StatusCode, f.remote)\n\t}\n\n\tvar set jose.JSONWebKeySet\n\tif err := json.NewDecoder(res.Body).Decode(&set); err != nil {\n\t\treturn nil, errors.WithStack(err)\n\t}\n\n\tfor _, k := range set.Keys {\n\t\tf.Lock()\n\t\tf.keys[k.KeyID] = k\n\t\tf.Unlock()\n\t}\n\n\tf.RLock()\n\tdefer f.RUnlock()\n\tif k, ok := f.keys[kid]; ok {\n\t\treturn &k, nil\n\t}","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/ory/hydra/blob/4174065ffb052799890f7480f5360a877a67ffc1/oryx/jwksx/fetcher.go#L35-L71","documentation":"Fetcher.GetKey fetches a JWKS document from f.remote over plain HTTP GET and requires HTTP 200. Any other status (404 wrong path, 401/403 auth required, 500 server error, 301/302 if redirects are not followed) aborts with this error instead of attempting to parse the body. It reports both the received status code and the requested URL.","triggerScenarios":"Calling jwksx.NewFetcher(remote).GetKey(kid) where the HTTP GET of the JWKS URL (oryx/jwksx/fetcher.go:53) returns a non-200 status — first fetch or any cache-miss fetch.","commonSituations":"Misconfigured issuer/JWKS URL (404), the JWKS endpoint requiring auth (401/403), the identity provider being down (5xx), or pointing at an HTML page instead of a JWKS endpoint.","solutions":["Verify the remote URL is the correct, complete JWKS endpoint (usually issuer + '/.well-known/jwks.json' or from the OpenID discovery 'jwks_uri').","Check server logs / curl the URL to see the actual status and response body for the real cause (401 vs 404 vs 500).","If the endpoint requires auth or is behind a proxy, configure an http.Client with the needed transport before constructing the fetcher.","Implement retry with backoff for transient 5xx responses, and cache keys so a brief outage does not break verification."],"exampleFix":"// before\nf := jwksx.NewFetcher(\"https://issuer.example.com/jwks\") // 404\n// after\nf := jwksx.NewFetcher(\"https://issuer.example.com/.well-known/jwks.json\")","handlingStrategy":"retry","validationCode":"resp, err := http.Head(jwksURL)\nif err != nil || resp.StatusCode != 200 {\n    return fmt.Errorf(\"JWKS URL %s not healthy (status %v)\", jwksURL, statusOrNil(resp))\n}","typeGuard":null,"tryCatchPattern":"key, err := fetcher.GetKey(kid)\nif err != nil && strings.Contains(err.Error(), \"expected status code 200\") {\n    time.Sleep(backoff)\n    key, err = fetcher.GetKey(kid) // retry transient 5xx\n}","preventionTips":["Point the fetcher at the exact jwks_uri from OpenID discovery.","Smoke-test the JWKS URL on deploy; alert on non-200.","Cache keys to tolerate brief JWKS endpoint outages."],"tags":["http","jwks","network"],"backgroundTag":"unexpected-http-status","analyzedSha":"4174065ffb052799890f7480f5360a877a67ffc1","analyzedAt":"2026-09-03T14:52:41.581Z","contentChangedAt":"2026-09-03T14:52:41.581Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}