{"record":{"id":"26cc2c75259f076b","repo":"karatelabs/karate","slug":"incomplete-http-request-url-not-set","errorCode":null,"errorMessage":"incomplete http request, 'url' not set","messagePattern":"incomplete http request, 'url' not set","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"karate-core/src/main/java/io/karatelabs/http/HttpRequestBuilder.java","lineNumber":450,"sourceCode":"                        segments.addAll(StringUtils.split(item, '/', true));\n                    }\n                }\n                builder.setPathSegments(segments);\n            }\n            URI uri = builder.build();\n            return uri.toASCIIString();\n        } catch (URISyntaxException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    // Destructive: drains multiPart form fields into URL params when method resolves to GET,\n    // and consumes multiPart into body bytes otherwise. Callers must set method() before\n    // calling build() on a form/multipart request, or the GET default below will silently\n    // rewrite the request.\n    private void buildInternal() {\n        if (url == null) {\n            throw new RuntimeException(\"incomplete http request, 'url' not set\");\n        }\n        if (method == null) {\n            if (multiPart != null && multiPart.isMultipart()) {\n                method = \"POST\";\n            } else {\n                method = \"GET\";\n            }\n        }\n        method = method.toUpperCase();\n        if (\"GET\".equals(method) && multiPart != null) {\n            Map<String, Object> parts = multiPart.getFormFields();\n            if (parts != null) {\n                parts.forEach((k, v) -> param(k, (String) v));\n            }\n            multiPart = null;\n        }\n        if (multiPart != null) {\n            if (body == null) { // this is not-null only for a re-try, don't rebuild multi-part","sourceCodeStart":432,"sourceCodeEnd":468,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/http/HttpRequestBuilder.java#L432-L468","documentation":"HttpRequestBuilder.buildInternal() validates that a target URL was configured before assembling the request. If url is still null — nothing called url(...) and no default was supplied — the request is incomplete and the builder throws instead of producing a malformed HttpRequest.","triggerScenarios":"Calling build()/invoke()/method()/response() on a builder where url() was never called; passing null to url(); clearing/reset flows that wipe the URL before a second build; using toCurlCommand() on a freshly created builder.","commonSituations":"Programmatic HTTP calls in Java tests where the URL comes from config/env and the property was empty or missing; template substitution producing empty strings handled as null; copy-pasted builder chains missing the url() line.","solutions":["Set the URL before executing: builder.url(\"https://host/path\")","Validate the config/env value feeding the URL is non-null and non-empty at startup","Guard dynamic URL construction: throw your own descriptive error if baseUrl is blank","If you only wanted the request shape for logging, still set a placeholder URL or use toCurlCommand() only after url() is called"],"exampleFix":"// before\nHttpRequestBuilder b = new HttpRequestBuilder(client);\nb.invoke(); // throws, url never set\n// after\nHttpRequestBuilder b = new HttpRequestBuilder(client);\nb.url(\"https://api.example.com/v1/users\").invoke();","handlingStrategy":"validation","validationCode":"if (baseUrl == null || baseUrl.isEmpty()) throw new IllegalArgumentException('request URL is not configured');\nbuilder.url(baseUrl + path);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always call url() before build()/invoke()/method()/response()","Validate config/env-provided base URLs at startup","Fail your own tests early when template substitution yields a blank URL"],"tags":["http","url","builder","missing-argument"],"backgroundTag":"invalid-url","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"}