antlr/antlr4 · error · MojoExecutionException

ANTLR 4 caught {} build errors.

Error message

ANTLR 4 caught {} build errors.

What it means

During pattern compilation a tag whose first character is neither uppercase (token convention) nor lowercase (rule convention) — for example a digit or punctuation — cannot be classified, so the matcher throws IllegalArgumentException 'invalid tag'. Tag content must start with an ASCII letter to be resolvable against the grammar.

Source

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

			}

            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());
        }

        try {
            dependencies.save();
        } catch (IOException ex) {
            log.warn("Could not save grammar dependency status", ex);
        }
    }

	private List<String> getCommandArguments() {
		List<String> args = new ArrayList<String>();

View on GitHub (pinned to 7d5770395b)

Solutions

  1. Make every tag start with an ASCII letter (uppercase = token, lowercase = rule).
  2. Validate pattern tags against ^[A-Za-z][A-Za-z0-9_]*$ before passing user input to compile().
  3. If you intended literal text, do not wrap it in tag delimiters.

Example fix

// before
ParseTreePattern p = m.compile("<1stArg> = <ID>", R.assign);

// after
ParseTreePattern p = m.compile("<firstArg> = <ID>", R.assign);
Defensive patterns

Strategy: validation

Validate before calling

private static final Pattern TAG = Pattern.compile("^[A-Za-z][A-Za-z0-9_]*$");
boolean tagOk(String tag) { return TAG.matcher(tag).matches(); }
// validate before compile
for (String tag : extractTags(patternText)) {
    if (!tagOk(tag)) throw new IllegalArgumentException("bad tag: " + tag);
}

Type guard

boolean isValidTagStart(char c) { return Character.isLetter(c); }

Try / catch

try {
    pattern = matcher.compile(userPattern, ruleIndex);
} catch (IllegalArgumentException e) {
    if (e.getMessage().startsWith("invalid tag")) {
        showTagSyntaxHelp(userPattern);
    }
    throw e;
}

Prevention

When it happens

Trigger: Patterns containing tags like <9id>, <_foo>, or non-ASCII leading characters; also tags that degenerate to empty after delimiter changes (e.g. setDelimiters misconfiguration making the tag body start at a non-letter).

Common situations: User-supplied pattern strings from a DSL or REPL; delimiters customized such that the extracted tag text starts with a symbol; generating patterns programmatically without validating tag names.

Related errors


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