languagetool-org/languagetool · error · IOException
Could not load false friend rules from
Error message
Could not load false friend rules from
What it means
FalseFriendRuleLoader.getRules reads a false-friend XML file and parses it. If the XML parser is misconfigured (ParserConfigurationException) or the document is malformed (SAXException), the loader wraps the cause in an IOException with this message plus the file path, so callers only need to handle IOException.
Source
Thrown at languagetool-core/src/main/java/org/languagetool/rules/patterns/FalseFriendRuleLoader.java:69
this.falseFriendSugg = messages.getString("false_friend_suggestion");
this.inTestMode = inTestMode;
}
public FalseFriendRuleLoader(String falseFriendHint, String falseFriendSugg) {
this.falseFriendHint = Objects.requireNonNull(falseFriendHint);
this.falseFriendSugg = Objects.requireNonNull(falseFriendSugg);
this.inTestMode = false;
}
/**
* @param file XML file with false friend rules
* @since 2.3
*/
public final List<AbstractPatternRule> getRules(File file, Language language, Language motherTongue) throws IOException {
try (InputStream inputStream = new FileInputStream(file)) {
return getRules(inputStream, language, motherTongue);
} catch (ParserConfigurationException | SAXException e) {
throw new IOException("Could not load false friend rules from " + file, e);
}
}
public final List<AbstractPatternRule> getRules(InputStream stream,
Language textLanguage, Language motherTongue)
throws ParserConfigurationException, SAXException, IOException {
FalseFriendRuleHandler handler = new FalseFriendRuleHandler(
textLanguage, motherTongue, falseFriendHint, inTestMode);
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser saxParser = factory.newSAXParser();
saxParser.getXMLReader().setFeature(
"http://apache.org/xml/features/nonvalidating/load-external-dtd",
false);
saxParser.parse(stream, handler);
List<AbstractPatternRule> rules = handler.getRules();
List<AbstractPatternRule> filteredRules = new ArrayList<>();
// Add suggestions to each rule:
MessageFormat msgFormat = new MessageFormat(falseFriendSugg);View on GitHub (pinned to 2e990059ce)
Solutions
- Validate the false-friend XML file with an XML parser/linter to find the malformed element reported in the chained cause
- Fix the XML syntax error at the location given by the wrapped SAXException
- Ensure the file encoding matches the XML declaration (usually UTF-8)
- Check DTD/stylesheet references resolve (network access or local copies for offline builds)
Example fix
// before (malformed) <rule id="X"> <translation lang="de">...</translation> </rul> // after <rule id="X"> <translation lang="de">...</translation> </rule>
Defensive patterns
Strategy: try-catch
Validate before calling
try (InputStream in = new FileInputStream(file)) {
new XmlDocumentBuilderFactory().newDocumentBuilder().parse(in); // pre-validate well-formedness
} Try / catch
try {
rules = loader.getRules(file, language, motherTongue);
} catch (IOException e) {
Throwable cause = e.getCause();
if (cause instanceof SAXException) {
log.error("Malformed false-friend XML at {}: {}", file, cause.getMessage());
}
throw e;
} Prevention
- Validate rule XML files in CI before shipping
- Keep files UTF-8 and consistent with the XML declaration
- Ensure DTD/external references resolve in offline builds
When it happens
Trigger: Calling getRules(File, Language, Language) (directly or via loadFalseFriendRules/tests) on an XML file that is not well-formed: unclosed tags, invalid entities, encoding problems, or an unreachable/invalid DTD.
Common situations: Editing false-friends.xml and breaking its structure, wrong file encoding (not UTF-8), missing external DTD in offline environments, or pointing the loader at the wrong XML file type.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- 'triggers_error' is not supported for false friend XML
- Translation language (
- Cannot load or parse '" + filename + "'
- <resultDir> already exists, but is a file:
AI-assisted analysis of languagetool-org/languagetool@2e990059ce (2026-09-06).
Data as JSON: /api/errors/4608279106ef1de2.
Report an issue: GitHub.