{"record":{"id":"4eb0e5d693d31789","repo":"jhy/jsoup","slug":"invalid-url-host-is-missing","errorCode":null,"errorMessage":"Invalid URL: host is missing","messagePattern":"Invalid URL: host is missing","errorType":"exception","errorClass":"MalformedURLException","httpStatus":null,"severity":"error","filePath":"src/main/java/org/jsoup/internal/StringUtil.java","lineNumber":354,"sourceCode":"        } catch (MalformedURLException e) {\n            try {\n                // the base is unsuitable, or resolution failed; the attribute/rel may be abs on its own\n                URL abs = new URL(relUrl);\n                validateHttpUrl(abs);\n                return abs.toExternalForm();\n            } catch (MalformedURLException ignored) {\n                // it may still be valid, just that Java doesn't have a registered stream handler for it, e.g. tel\n                // we test here vs at start to normalize supported URLs (e.g. HTTP -> http)\n                return validUriScheme.matcher(relUrl).find() && !hasHttpScheme(relUrl) ? relUrl : \"\";\n            }\n        }\n    }\n    private static final Pattern validUriScheme = Pattern.compile(\"^[a-zA-Z][a-zA-Z0-9+-.]*:\");\n\n    /** Validates that an HTTP(S) URL has the host required by its scheme. */\n    private static void validateHttpUrl(URL url) throws MalformedURLException {\n        if (isHttpScheme(url.getProtocol()) && url.getHost().isEmpty())\n            throw new MalformedURLException(\"Invalid URL: host is missing\");\n    }\n\n    /** Tests if the supplied scheme is HTTP or HTTPS. */\n    public static boolean isHttpScheme(String scheme) {\n        return scheme.equalsIgnoreCase(\"http\") || scheme.equalsIgnoreCase(\"https\");\n    }\n\n    /** Tests if the supplied value starts with an HTTP or HTTPS scheme. */\n    public static boolean hasHttpScheme(String value) {\n        int colon = value.indexOf(':');\n        return colon > 0 && isHttpScheme(value.substring(0, colon));\n    }\n\n    private static final Pattern controlChars = Pattern.compile(\"[\\\\x00-\\\\x1f]*\"); // matches ascii 0 - 31, to strip from url\n    private static String stripControlChars(final String input) {\n        return controlChars.matcher(input).replaceAll(\"\");\n    }\n","sourceCodeStart":336,"sourceCodeEnd":372,"githubUrl":"https://github.com/jhy/jsoup/blob/9851ac5d9c576c6888910b5a51a2362bbc978959/src/main/java/org/jsoup/internal/StringUtil.java#L336-L372","documentation":"jsoup validates that URLs with an http or https scheme include a non-empty host. Because a relative or malformed URL string like 'http://' has no host, StringUtil.resolve rejects it with a MalformedURLException rather than producing a useless base-less URL object.","triggerScenarios":"Calling jsoup URL resolution (e.g. StringUtil.resolve / URL resolution during link handling) with a URL string whose scheme is http/https but which lacks a host, such as 'http://', 'https:///path', or a base URL typed without the domain.","commonSituations":"Users entering incomplete URLs in forms or config files (missing domain), string concatenation that drops the host, or trimming/mangling a base URI before parsing.","solutions":["Fix the URL string so it includes a host, e.g. 'http://example.com/path' instead of 'http:///path'","Validate the URL in your own code with new URI(s) or new URL(s) and check getHost() != null before handing it to jsoup","If the value may be relative, resolve it against a known valid base URL before use","Catch MalformedURLException and surface a user-facing 'enter a complete URL including domain' message"],"exampleFix":"// before\nString url = \"http://\";\nDocument doc = Jsoup.connect(url).get(); // MalformedURLException\n// after\nString url = \"http://example.com\";\nif (new URL(url).getHost().isEmpty()) throw new IllegalArgumentException(\"URL needs a host\");\nDocument doc = Jsoup.connect(url).get();","handlingStrategy":"validation","validationCode":"import java.net.URL;\nboolean hasHost(String s) throws MalformedURLException { return new URL(s).getHost() != null && !new URL(s).getHost().isEmpty(); }","typeGuard":null,"tryCatchPattern":"try { Document doc = Jsoup.connect(url).get(); } catch (MalformedURLException e) { throw new IllegalArgumentException(\"Provide a full URL with a host, e.g. http://example.com\", e); }","preventionTips":["Validate URLs with java.net.URI/URL before use","Always include scheme and host when building URLs from strings","Resolve relative links against a known-good base URI","Never concatenate user input into URL strings without validation"],"tags":["url","validation","http"],"backgroundTag":"invalid-url","analyzedSha":"9851ac5d9c576c6888910b5a51a2362bbc978959","analyzedAt":"2026-09-08T15:22:04.931Z","contentChangedAt":"2026-09-08T15:22:04.931Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}