{"record":{"id":"9e617a8470a98db6","repo":"GoogleContainerTools/jib","slug":"expected-1-location-header-but-found-headerco","errorCode":null,"errorMessage":"Expected 1 'Location' header, but found ${headerCount}","messagePattern":"Expected 1 'Location' header, but found (.+?)","errorType":"exception","errorClass":"RegistryErrorException","httpStatus":null,"severity":"error","filePath":"jib-core/src/main/java/com/google/cloud/tools/jib/registry/BlobPusher.java","lineNumber":294,"sourceCode":"  }\n\n  /**\n   * Extract the {@code Location} header from the response to get the new location for the next\n   * request.\n   *\n   * <p>The {@code Location} header can be relative or absolute.\n   *\n   * @see <a\n   *     href=\"https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location#Directives\">https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Location#Directives</a>\n   * @param response the response to extract the 'Location' header from\n   * @return the new location for the next request\n   * @throws RegistryErrorException if there was not a single 'Location' header\n   */\n  private URL getRedirectLocation(Response response) throws RegistryErrorException {\n    // Extracts and returns the 'Location' header.\n    List<String> locationHeaders = response.getHeader(\"Location\");\n    if (locationHeaders.size() != 1) {\n      throw buildRegistryErrorException(\n          \"Expected 1 'Location' header, but found \" + locationHeaders.size());\n    }\n\n    String locationHeader = locationHeaders.get(0);\n    return response.getRequestUrl().toURL(locationHeader);\n  }\n}\n","sourceCodeStart":276,"sourceCodeEnd":302,"githubUrl":"https://github.com/GoogleContainerTools/jib/blob/fb949e2676afbbd7dd7a1ef61e20251931325654/jib-core/src/main/java/com/google/cloud/tools/jib/registry/BlobPusher.java#L276-L302","documentation":"When the registry responds 202 Accepted to a blob upload, Jib requires exactly one 'Location' header telling it where to continue the upload. If zero or multiple Location headers are present, the registry response violates the expected protocol and Jib throws a RegistryErrorException.","triggerScenarios":"A registry (or intermediary proxy) responding 202 to a blob push PATCH/PUT with no Location header, or duplicating the Location header.","commonSituations":"Custom or older private registries that omit Location on 202; reverse proxies that add or duplicate headers; CDN/middleware rewriting upload responses.","solutions":["Fix or replace the non-compliant registry/proxy so a single Location header is returned with 202 responses","Check intermediary proxies for header manipulation (e.g. duplicate add_header directives)","Retry against the registry directly without a proxy to confirm where the bad response originates","Use a spec-compliant registry (Distribution/registry:2, GCR, ECR, Docker Hub)"],"exampleFix":"// nginx proxy before\nadd_header Location $upstream_http_location;\nadd_header Location $upstream_http_location;\n// after\nproxy_pass_header Location;","handlingStrategy":"validation","validationCode":"// preflight blob push and inspect Location header\ncurl -i -X POST https://registry:5000/v2/myapp/blobs/uploads/ | grep -i '^location:'","typeGuard":null,"tryCatchPattern":"try {\n  jibBuild.push();\n} catch (RegistryErrorException e) {\n  if (e.getMessage().contains(\"'Location' header\")) {\n    System.err.println(\"Registry/proxy is dropping or duplicating Location headers\");\n  }\n}","preventionTips":["Ensure proxies use proxy_pass_header / proxy_set_header correctly instead of duplicating add_header","Upgrade old private registry software that omits Location on 202","Verify header behavior with curl before CI pushes"],"tags":["registry","http-headers","docker","push"],"backgroundTag":"unexpected-response-shape","analyzedSha":"fb949e2676afbbd7dd7a1ef61e20251931325654","analyzedAt":"2026-09-06T14:04:09.491Z","contentChangedAt":"2026-09-06T14:04:09.491Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}