{"record":{"id":"647a6b256b695e9d","repo":"keycloak/keycloak","slug":"resourceid-is-not-found-in-location-header-from-re","errorCode":null,"errorMessage":"resourceId is not found in Location header from request: ${res.url}","messagePattern":"resourceId is not found in Location header from request: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"js/libs/keycloak-admin-client/src/resources/agent.ts","lineNumber":273,"sourceCode":"      });\n\n      // now we get the response of the http request\n      // if `resourceIdInLocationHeader` is true, we'll get the resourceId from the location header field\n      // todo: find a better way to find the id in path, maybe some kind of pattern matching\n      // for now, we simply split the last sub-path of the path returned in location header field\n      if (returnResourceIdInLocationHeader) {\n        const locationHeader = res.headers.get(\"location\");\n\n        if (typeof locationHeader !== \"string\") {\n          throw new Error(\n            `location header is not found in request: ${res.url}`,\n          );\n        }\n\n        const resourceId = locationHeader.split(SLASH).pop();\n        if (!resourceId) {\n          // throw an error to let users know the response is not expected\n          throw new Error(\n            `resourceId is not found in Location header from request: ${res.url}`,\n          );\n        }\n\n        // return with format {[field]: string}\n        const { field } = returnResourceIdInLocationHeader;\n        return { [field]: resourceId };\n      }\n\n      if (\n        Object.entries(headers || []).find(\n          ([key, value]) =>\n            key.toLowerCase() === \"accept\" &&\n            value === \"application/octet-stream\",\n        )\n      ) {\n        return await res.arrayBuffer();\n      }","sourceCodeStart":255,"sourceCodeEnd":291,"githubUrl":"https://github.com/keycloak/keycloak/blob/66c7e15a3788de7764f07dd2558275a02770e16d/js/libs/keycloak-admin-client/src/resources/agent.ts#L255-L291","documentation":"Thrown by the admin-client agent after a `location` header was found, but splitting it on `/` and taking the last segment yields an empty string. This means the Location header is malformed for id extraction (e.g. it ends with a trailing slash or is a bare host), so the agent cannot derive a resource id and surfaces the unexpected shape.","triggerScenarios":"The `Location` header is `https://host/realms/master/clients/` (trailing slash), a bare `https://host/`, or otherwise ends in a delimiter; the header points somewhere the naive `split('/').pop()` heuristic cannot parse.","commonSituations":"Server or proxy normalises URLs and appends a trailing slash; the Location is an external/absolute URL whose last path segment is empty; a routing layer rewrites the Location value.","solutions":["Log the raw `location` header value to see its exact shape.","If the server appends a trailing slash, normalise/proxy-fix so the Location ends with the new id.","Avoid `returnResourceIdInLocationHeader` for that resource and read the id from the response body if available.","Report the malformed Location to the backend/proxy owner if it is a regression."],"exampleFix":"// before\nreturn { [field]: locationHeader.split(SLASH).pop() };\n\n// after: tolerate trailing slashes\nconst trimmed = locationHeader.replace(/\\/+$/, '');\nconst resourceId = trimmed.split(SLASH).pop();","handlingStrategy":"validation","validationCode":"function extractResourceId(location: string): string | undefined {\n  const trimmed = location.replace(/\\/+$/, '');\n  const id = trimmed.split('/').pop();\n  return id || undefined;\n}","typeGuard":"const locationHasTrailingId = (location: string): boolean =>\n  Boolean(location.replace(/\\/+$/, '').split('/').pop());","tryCatchPattern":"try {\n  const { id } = await kcAdminClient.clients.create({ ...payload });\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('resourceId is not found in Location header')) {\n    // Location malformed; fall back to listing/lookup\n  } else throw e;\n}","preventionTips":["Inspect the raw Location value when this fires to spot trailing slashes.","Fix proxy/server URL normalisation that appends trailing slashes to Location.","Fall back to body-based id lookup when Location parsing is unreliable."],"tags":["network","http","headers","admin-client","create","parsing"],"backgroundTag":null,"analyzedSha":"66c7e15a3788de7764f07dd2558275a02770e16d","analyzedAt":"2026-08-14T01:36:42.651Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}