{"record":{"id":"c3a29b25ec4888f3","repo":"karatelabs/karate","slug":"proceed-needs-a-target-url-or-host-header-in-request-c3a29b","errorCode":null,"errorMessage":"proceed() needs a target URL or Host header in request","messagePattern":"proceed\\(\\) needs a target URL or Host header in request","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"karate-core/src/main/java/io/karatelabs/http/HttpRequest.java","lineNumber":709,"sourceCode":"        return args -> {\n            if (args.length > 0) {\n                return getFiles(args[0] + \"\");\n            } else {\n                throw new RuntimeException(\"missing argument for files()\");\n            }\n        };\n    }\n\n    /**\n     * Forward this request to a target URL and return the response.\n     * Mirrors {@code karate.proceed()} so JS-file mocks can implement proxy behavior.\n     * If {@code targetUrl} is null, uses the {@code Host} header on this request.\n     */\n    public HttpResponse proceed(String targetUrl) {\n        if (targetUrl == null) {\n            String host = getHeader(\"Host\");\n            if (host == null) {\n                throw new RuntimeException(\"proceed() needs a target URL or Host header in request\");\n            }\n            targetUrl = \"http://\" + host;\n        }\n        HttpClient client = httpClient != null ? httpClient : new DefaultHttpClientFactory().create();\n        HttpRequestBuilder builder = new HttpRequestBuilder(client);\n        builder.url(targetUrl);\n        builder.path(path);\n        builder.method(method);\n        if (headers != null) {\n            headers.forEach((name, values) -> {\n                String lowerName = name.toLowerCase();\n                if (!lowerName.equals(\"content-length\") && !lowerName.equals(\"host\")\n                        && !lowerName.equals(\"transfer-encoding\")) {\n                    builder.header(name, values);\n                }\n            });\n        }\n        Object converted = getBodyConverted();","sourceCodeStart":691,"sourceCodeEnd":727,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/http/HttpRequest.java#L691-L727","documentation":"HttpRequest.proceed(targetUrl) re-sends/replays the request against a new target. If targetUrl is null it falls back to building http://<Host header>. When neither a target URL nor a Host header exists there is nowhere to forward the request, so it throws.","triggerScenarios":"Calling request.proceed(null) (or proceed() via a binding that omits the arg) on a request that has no 'Host' header set — e.g. a request built programmatically with only a path, or a request whose Host header was stripped by an intermediary or by the caller before proceeding.","commonSituations":"Implementing proxy/redirect-following logic where the upstream response/request lost its Host header; testing forward() style flows with hand-built HttpRequest objects; environment changes where requests previously came with Host headers but now come from a builder that never set one.","solutions":["Pass an explicit target: request.proceed(\"https://other-host.example\")","Set a Host header before proceeding: request.header(\"Host\", \"other-host.example\") then proceed(null)","If replaying on the same host, pass the original base URL rather than null","When intercepting/proxying, copy the inbound Host header onto the HttpRequest before calling proceed"],"exampleFix":"// before\nresponse.getRequest().proceed(null); // throws when Host header absent\n// after\nresponse.getRequest().proceed(\"http://backend.internal:8080\");","handlingStrategy":"try-catch","validationCode":"var req = response.getRequest();\nif (targetUrl == null && req.getHeader(\"Host\") == null) {\n  throw new Error('proceed() requires a target URL; request has no Host header');\n}","typeGuard":null,"tryCatchPattern":"try {\n  response.getRequest().proceed(targetUrl);\n} catch (RuntimeException e) {\n  if (e.getMessage().contains(\"proceed() needs a target URL\")) {\n    // fall back to the original absolute URL\n    response.getRequest().proceed(originalBaseUrl);\n  } else { throw e; }\n}","preventionTips":["Always pass an explicit absolute target URL to proceed()","When proxying, copy the inbound Host header onto the rebuilt request","Never rely on the Host fallback for programmatically-built requests"],"tags":["http","proxy","url","host-header"],"backgroundTag":"invalid-state-transition","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-16T19:17:19.609Z"}