antlr/antlr4 · error · MojoFailureException

Dependency analysis failed.

Error message

Dependency analysis failed.

What it means

The lowercase counterpart of the token check: a tag starting lowercase (e.g. <expr>) is treated as a rule reference; the matcher calls parser.getRuleIndex(tag) and receives -1 when the grammar has no such rule, then throws IllegalArgumentException with the unknown rule name. The rule must exist because the pattern will be matched as that rule's structure.

Source

Thrown at antlr4-maven-plugin/src/main/java/org/antlr/mojo/antlr4/Antlr4Mojo.java:290

        }

		log.debug("Output directory base will be " + outputDirectory.getAbsolutePath());
		log.info("ANTLR 4: Processing source directory " + sourceDirectory.getAbsolutePath());
		for (List<String> args : argumentSets) {
			try {
				// Create an instance of the ANTLR 4 build tool
				tool = new CustomTool(args.toArray(new String[0]));
			} catch (Exception e) {
				log.error("The attempt to create the ANTLR 4 build tool failed, see exception report for details", e);
				throw new MojoFailureException("Error creating an instanceof the ANTLR tool.", e);
			}

            try {
                dependencies.analyze(grammarFiles, importGrammarFiles, tool);
            } catch (Exception e) {
                log.error("Dependency analysis failed, see exception report for details",
                    e);
                throw new MojoFailureException("Dependency analysis failed.", e);
            }

			// Set working directory for ANTLR to be the base source directory
			tool.inputDirectory = sourceDirectory;

			tool.processGrammarsOnCommandLine();

			// If any of the grammar files caused errors but did nto throw exceptions
			// then we should have accumulated errors in the counts
			if (tool.getNumErrors() > 0) {
				throw new MojoExecutionException("ANTLR 4 caught " + tool.getNumErrors() + " build errors.");
			}
		}

        if (project != null) {
            // Tell Maven that there are some new source files underneath the output directory.
            addSourceRoot(this.getOutputDirectory());
        }

View on GitHub (pinned to 7d5770395b)

Solutions

  1. Verify the rule name against the generated parser's rule names (R.xxx constants or the grammar file).
  2. Use the generated rule-index constants rather than strings where possible to keep names in sync.
  3. Recompile patterns in tests whenever the grammar changes.

Example fix

// before
ParseTreePattern p = m.compile("<ident> : <ID>", R.stmt); // rule is 'identifier'

// after
ParseTreePattern p = m.compile("<identifier> : <ID>", R.stmt);
Defensive patterns

Strategy: try-catch

Validate before calling

if (Character.isLowerCase(tag.charAt(0)) && parser.getRuleIndex(tag) == -1) {
    throw new IllegalArgumentException("not a rule in this grammar: " + tag);
}

Type guard

boolean isKnownRule(Parser p, String tag) {
    return Character.isLowerCase(tag.charAt(0)) && p.getRuleIndex(tag) != -1;
}

Try / catch

try {
    pattern = matcher.compile(patternText, ruleIndex);
} catch (IllegalArgumentException e) {
    if (e.getMessage().startsWith("Unknown rule")) {
        // rule renamed in grammar: update pattern strings
        reportStalePattern(patternText);
    }
    throw e;
}

Prevention

When it happens

Trigger: Compiling a pattern with a rule tag that does not exist in the grammar (misspelling, renamed rule, or a rule from another grammar); passing the wrong patternRuleIndex context so the name lookup fails.

Common situations: Grammar refactors that rename rules without updating pattern strings embedded in application code; patterns shared across multiple grammars; typo-level mistakes like <ident> vs <identifier>.

Related errors


AI-assisted analysis of antlr/antlr4@7d5770395b (2026-08-14). Data as JSON: /api/errors/2e3e42219bb20c5c. Report an issue: GitHub.