{"record":{"id":"b4ff60184945c4f6","repo":"languagetool-org/languagetool","slug":"cannot-load-or-parse-input-stream-of-filename","errorCode":null,"errorMessage":"Cannot load or parse input stream of '${filename}'","messagePattern":"Cannot load or parse input stream of '(.+?)'","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"languagetool-core/src/main/java/org/languagetool/rules/patterns/PatternRuleLoader.java","lineNumber":82,"sourceCode":"   * @param filename used only for verbose exception message - should refer to where the stream comes from\n   */\n  public final List<AbstractPatternRule> getRules(InputStream is, String filename, Language lang) throws IOException {\n    try {\n      PatternRuleHandler handler = new PatternRuleHandler(filename, lang);\n      handler.setRelaxedMode(relaxedMode);\n      SAXParserFactory factory = SAXParserFactory.newInstance();\n      SAXParser saxParser = factory.newSAXParser();\n      if (JLanguageTool.isCustomPasswordAuthenticatorUsed()) {\n        Tools.setPasswordAuthenticator();\n      }\n      saxParser.getXMLReader().setFeature(\"http://apache.org/xml/features/nonvalidating/load-external-dtd\", false);\n      saxParser.getXMLReader().setProperty(\"jdk.xml.maxGeneralEntitySizeLimit\", 0);\n      saxParser.getXMLReader().setProperty(\"jdk.xml.totalEntitySizeLimit\", 0);\n      saxParser.getXMLReader().setProperty(\"jdk.xml.entityExpansionLimit\", 0);\n      saxParser.parse(is, handler);\n      return handler.getRules();\n    } catch (Exception e) {\n      throw new IOException(\"Cannot load or parse input stream of '\" + filename + \"'\", e);\n    }\n  }\n\n}\n\n","sourceCodeStart":64,"sourceCodeEnd":88,"githubUrl":"https://github.com/languagetool-org/languagetool/blob/2e990059ce67d5e2a0f7f7ca5d31160c6709df4b/languagetool-core/src/main/java/org/languagetool/rules/patterns/PatternRuleLoader.java#L64-L88","documentation":"PatternRuleLoader.getRules() wraps any exception thrown while SAX-parsing a pattern rule XML file into an IOException with the filename in the message. LanguageTool throws it whenever the rule XML cannot be read or is not valid XML. The original cause is chained, so inspect e.getCause() for the real XML error.","triggerScenarios":"Calling getRules(InputStream, String filename) where the stream is unreadable, empty, closed, or contains malformed XML (e.g. PatternRuleLoaderHandler fails on bad element/attribute), including during externalRules/loadPatternRules/initializePatternRules.","commonSituations":"Typo or unescaped character (&, <) in a custom grammar .xml rule file; missing file packaged into resources; encoding mismatch (file not UTF-8); corrupted stream after an earlier read; entity limits were configured away in this version (jdk.xml.maxGeneralEntitySizeLimit etc. set to 0).","solutions":["Inspect the chained cause (e.getCause()) to find the exact XML parse error and line number, then fix the XML syntax in the rule file.","Verify the file exists on the classpath/disk and the InputStream is valid and not already consumed before calling getRules.","Ensure the XML is well-formed and matches the expected rule DTD/structure, including proper encoding declaration.","Catch the IOException at the call site and surface a user-friendly message naming the offending rule file."],"exampleFix":"// before\nList<Rule> rules = loader.getRules(is, \"myRules.xml\");\n// after\nif (is == null || is.read() == -1) { throw new IllegalStateException(\"myRules.xml missing or empty\"); }\ntry {\n  List<Rule> rules = loader.getRules(is, \"myRules.xml\");\n} catch (IOException e) {\n  logger.error(\"Invalid rule file myRules.xml: \" + e.getCause(), e);\n}","handlingStrategy":"try-catch","validationCode":"// before loading\nFile f = new File(\"myRules.xml\");\nif (!f.isFile() || f.length() == 0) throw new IllegalStateException(\"Rule file missing/empty: \" + f);\ntry (InputStream is = new BufferedInputStream(new FileInputStream(f))) { /* validate XML with a parser first */ }","typeGuard":null,"tryCatchPattern":"try {\n  rules = loader.getRules(is, filename);\n} catch (IOException e) {\n  throw new RuleLoadException(\"Bad rule file \" + filename + \": \" + e.getCause(), e);\n}","preventionTips":["Validate rule XML files with an XML parser/XSD check in CI before shipping them.","Always check file existence and non-empty stream before getRules.","Keep rule files UTF-8 with a correct XML declaration.","Log e.getCause(), not just the wrapper, when diagnosing."],"tags":["io","xml","parsing","java"],"backgroundTag":"file-read-failed","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"}