{"record":{"id":"7be9b7cc6bc05579","repo":"languagetool-org/languagetool","slug":"could-not-parse-url-for-rule","errorCode":null,"errorMessage":"Could not parse URL for rule: ","messagePattern":"Could not parse URL for rule: ","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"languagetool-core/src/main/java/org/languagetool/rules/patterns/PatternRuleHandler.java","lineNumber":918,"sourceCode":"    for (Match m : suggestionMatchesOutMsg) {\n      rule.addSuggestionMatchOutMsg(m);\n    }\n    suggestionMatchesOutMsg.clear();\n    if (category == null) {\n      throw new RuntimeException(\"Cannot activate rule '\" + id + \"', it is outside of a <category>...</category>\");\n    }\n    if (defaultOff) {\n      rule.setDefaultOff();\n    }\n    if (defaultTempOff) {\n      rule.setDefaultTempOff();\n    }\n    if (url != null && url.length() > 0) {\n      try {\n        String s = url.toString();\n        rule.setUrl(internUrl(s));\n      } catch (MalformedURLException e) {\n        throw new RuntimeException(\"Could not parse URL for rule: \" + rule + \": '\" + url + \"'\", e);\n      }\n    } else if (urlForRuleGroup != null && urlForRuleGroup.length() > 0) {\n      try {\n        rule.setUrl(internUrl(urlForRuleGroup.toString()));\n      } catch (MalformedURLException e) {\n        throw new RuntimeException(\"Could not parse URL for rule: \" + rule + \": '\" + urlForRuleGroup + \"'\", e);\n      }\n    }\n    // inheritance of values - if no type value is defined for a rule, take the rule group's value etc:\n    if (ruleIssueType != null) {\n      rule.setLocQualityIssueType(ITSIssueType.getIssueType(ruleIssueType));\n    } else if (ruleGroupIssueType != null) {\n      rule.setLocQualityIssueType(ITSIssueType.getIssueType(ruleGroupIssueType));\n    } else if (categoryIssueType != null) {\n      rule.setLocQualityIssueType(ITSIssueType.getIssueType(categoryIssueType));\n    }\n    int prio = 0;\n    if (prioCategoryAttribute != 0) {","sourceCodeStart":900,"sourceCodeEnd":936,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-core/src/main/java/org/languagetool/rules/patterns/PatternRuleHandler.java#L900-L936","documentation":"A rule's url attribute (or its inherited content) must be a syntactically valid absolute URL. prepareRule calls rule.setUrl(internUrl(s)); a MalformedURLException is rethrown as this RuntimeException, keeping the original as cause.","triggerScenarios":"<rule url=\"...\"> (rule-level url takes precedence) whose value fails java.net.URL parsing during XML rule loading.","commonSituations":"Missing scheme (\"example.com/page\" instead of \"https://example.com/page\"); spaces or unescaped characters in the URL; malformed entities after hand-editing XML.","solutions":["Add the scheme to the url attribute, e.g. https://...","URL-encode spaces and special characters in the attribute value","Validate the attribute with new java.net.URL(value) before shipping the XML"],"exampleFix":"// before\n<rule id=\"X\" url=\"example.com/docs\">...</rule>\n// after\n<rule id=\"X\" url=\"https://example.com/docs\">...</rule>","handlingStrategy":"validation","validationCode":"// Validate rule-level url attributes before loading\nNodeList rules = doc.getElementsByTagName(\"rule\");\nfor (int i = 0; i < rules.getLength(); i++) {\n  Node u = rules.item(i).getAttributes().getNamedItem(\"url\");\n  if (u != null) new java.net.URL(u.getNodeValue()); // throws MalformedURLException early\n}","typeGuard":null,"tryCatchPattern":"try { loader.parse(ruleXml, lang); } catch (RuntimeException e) { if (e.getMessage().startsWith(\"Could not parse URL\")) { log.error(\"Fix url attribute (add scheme, encode chars)\"); } throw e; }","preventionTips":["Always include https:// in url attributes","URL-encode spaces and non-ASCII characters","Check urls with new URL(value) or a validator in CI"],"tags":["xml","url","malformed-url","languagetool"],"backgroundTag":"invalid-url-format","analyzedSha":"2e990059ce67d5e2a0f7f7ca5d31160c6709df4b","analyzedAt":"2026-09-06T09:20:17.015Z","contentChangedAt":"2026-09-06T09:20:17.015Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}