{"record":{"id":"8a6bac00ae25f276","repo":"HMCL-dev/HMCL","slug":"invalid-url","errorCode":null,"errorMessage":"Invalid URL: ","messagePattern":"Invalid URL: ","errorType":"validation","errorClass":"JsonParseException","httpStatus":null,"severity":"error","filePath":"HMCL/src/main/java/org/jackhuang/hmcl/terracotta/TerracottaNodeList.java","lineNumber":48,"sourceCode":"import java.net.URI;\nimport java.net.URISyntaxException;\nimport java.util.List;\n\nimport static org.jackhuang.hmcl.util.logging.Logger.LOG;\n\n/// @author Glavo\npublic final class TerracottaNodeList {\n    private static final String NODE_LIST_URL = \"https://terracotta.glavo.site/nodes\";\n\n    @JsonSerializable\n    private record TerracottaNode(String url, @Nullable String region) implements Validation {\n        @Override\n        public void validate() throws JsonParseException, TolerableValidationException {\n            Validation.requireNonNull(url, \"TerracottaNode.url cannot be null\");\n            try {\n                new URI(url);\n            } catch (URISyntaxException e) {\n                throw new JsonParseException(\"Invalid URL: \" + url, e);\n            }\n        }\n    }\n\n    private static volatile List<URI> list;\n\n    public static List<URI> fetch() {\n        List<URI> list = TerracottaNodeList.list;\n        if (list != null)\n            return list;\n\n        synchronized (TerracottaNodeList.class) {\n            list = TerracottaNodeList.list;\n            if (list != null)\n                return list;\n\n            try {\n                List<TerracottaNode> nodes = HttpRequest.GET(NODE_LIST_URL)","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/HMCL-dev/HMCL/blob/24702dc5a0214034f4c27166d5fd30cad08cec19/HMCL/src/main/java/org/jackhuang/hmcl/terracotta/TerracottaNodeList.java#L30-L66","documentation":"TerracottaNode.validate parses the node's url string with java.net.URI to confirm it is syntactically valid; a URISyntaxException is rethrown as JsonParseException. The guard runs during JSON validation so malformed node URLs fail fast at config load.","triggerScenarios":"A terracotta node entry whose url string cannot be parsed by new URI(url) — missing scheme, illegal characters, spaces, unmatched brackets in host, etc.","commonSituations":"Hand-editing the terracotta node list; copying URLs with trailing whitespace or unencoded characters; forgetting the scheme (e.g. 'localhost:8080').","solutions":["Fix the url string to a valid RFC 2396 URI (include scheme, percent-encode special characters)","Trim whitespace and illegal characters from the url","Validate with new URI(candidate) locally before saving the config","Catch JsonParseException in the loader and reject/repair the offending node entry"],"exampleFix":"// before\n\"url\": \"my terracotta node:8080\"\n// after\n\"url\": \"https://my-terracotta-node:8080\"","handlingStrategy":"validation","validationCode":"Objects.requireNonNull(url, \"url\"); new URI(url.trim());","typeGuard":"static boolean validUrl(String url) { if (url == null || url.isBlank()) return false; try { new URI(url.trim()); return true; } catch (URISyntaxException e) { return false; } }","tryCatchPattern":"try { node.validate(); } catch (JsonParseException e) { LOG.warning(\"Rejecting malformed node URL\", e); }","preventionTips":["Encode spaces and special characters in URLs","Always specify scheme explicitly","Run URI syntax checks in config tooling before saving"],"tags":["url","validation","json"],"backgroundTag":"invalid-url","analyzedSha":"24702dc5a0214034f4c27166d5fd30cad08cec19","analyzedAt":"2026-09-10T12:36:46.680Z","contentChangedAt":"2026-09-10T12:36:46.680Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}