gradle/gradle · warning

unable to locate grammar exporting specified import vocab [{

Error message

unable to locate grammar exporting specified import vocab [{}]

What it means

For ANTLR 2 grammars, Gradle builds a GenerationPlan per grammar and cross-references each grammar's importVocab against the exportVocab declared by other grammar files in the same source set (metadataXRef.getGrammarFileByExportVocab). If no grammar exports the named vocabulary, the lookup returns null: Gradle warns and the importing grammar gets no importVocabTokenTypesDirectory, which usually surfaces as ANTLR generation errors (e.g. cannot find TokenTypes.txt) or mismatched token types.

Source

Thrown at platforms/jvm/antlr/src/main/java/org/gradle/api/plugins/antlr/internal/antlr2/GenerationPlanBuilder.java:101

                        .getAssociatedGrammarMetadata().getGrammarFile();
                if (superGrammarGrammarFileMetadata != null) {
                    final GenerationPlan superGrammarGenerationPlan = locateOrBuildGenerationPlan(
                            superGrammarGrammarFileMetadata);
                    if (superGrammarGenerationPlan.isOutOfDate()) {
                        generationPlan.markOutOfDate();
                    } else if (superGrammarGenerationPlan.getSource().lastModified() > generatedParserFile
                            .lastModified()) {
                        generationPlan.markOutOfDate();
                    }
                }
            }

            // see if the grammar if out-of-date by way of its importVocab
            if (isNotEmpty(grammarMetadata.getImportVocab())) {
                final GrammarFileMetadata importVocabGrammarFileMetadata = metadataXRef.getGrammarFileByExportVocab(
                        grammarMetadata.getImportVocab());
                if (importVocabGrammarFileMetadata == null) {
                    LOGGER.warn("unable to locate grammar exporting specified import vocab ["
                            + grammarMetadata.getImportVocab() + "]");
                } else if (!importVocabGrammarFileMetadata.getFilePath().equals(grammarFileMetadata.getFilePath())) {
                    final GenerationPlan importVocabGrammarGenerationPlan = locateOrBuildGenerationPlan(
                            importVocabGrammarFileMetadata);
                    generationPlan.setImportVocabTokenTypesDirectory(
                            importVocabGrammarGenerationPlan.getGenerationDirectory());
                    if (importVocabGrammarGenerationPlan.isOutOfDate()) {
                        generationPlan.markOutOfDate();
                    } else if (importVocabGrammarGenerationPlan.getSource().lastModified() > generatedParserFile
                            .lastModified()) {
                        generationPlan.markOutOfDate();
                    }
                }
            }
        }

        generationPlans.put(generationPlan.getId(), generationPlan);
        return generationPlan;

View on GitHub (pinned to 534f27719b)

Solutions

  1. Diff every importVocab=X against an exportVocab=X in the same antlr source set - names are case-sensitive
  2. Make sure the exporting grammar is actually included in the AntlrTask's sources (check includes/excludes and source set layout)
  3. Run ./gradlew clean generateGrammarSource so all generation plans are rebuilt once the link resolves
  4. If the vocabulary was renamed intentionally, update both sides: exportVocab in the token grammar and importVocab in every importing parser grammar

Example fix

// before: vocab names do not match -> warning + broken generation
// MyTokensParser.g: options { importVocab=MyToken; }   // typo
// MyTokens.g:       options { exportVocab=MyTokens; }

// after: names match exactly (case-sensitive)
// MyTokensParser.g: options { importVocab=MyTokens; }
// MyTokens.g:       options { exportVocab=MyTokens; }
Defensive patterns

Strategy: validation

Validate before calling

// build.gradle: fail fast if an importVocab has no matching exportVocab
tasks.register('validateGrammars') {
    doLast {
        def grammars = fileTree('src/main/antlr').matching { include '**/*.g' }
        def exports = grammars.files.collect { f ->
            (f.text =~ /exportVocab\s*=\s*(\w+)/).collect { it[1] }
        }.flatten().toSet()
        grammars.each { f ->
            (f.text =~ /importVocab\s*=\s*(\w+)/).each { m ->
                if (!exports.contains(m[1])) {
                    throw new GradleException("${f.name}: importVocab '${m[1]}' has no matching exportVocab")
                }
            }
        }
    }
}
tasks.named('generateGrammarSource') { dependsOn 'validateGrammars' }

Prevention

When it happens

Trigger: A grammar declares options { importVocab=MyTokens; } but no grammar passed to the same AntlrGenerateParserTask declares options { exportVocab=MyTokens; } - caused by a typo/case mismatch, a renamed vocab, or the exporting grammar living in a different source set or being excluded by the AntlrTask source filter.

Common situations: Typos or case mismatches between importVocab and exportVocab; multi-grammar token-sharing setups where one grammar file was moved, renamed, or excluded; migrating legacy AntlrPlugin configurations between projects or source sets.

Related errors


AI-assisted analysis of gradle/gradle@534f27719b (2026-08-22). Data as JSON: /api/errors/a2a294f2bfe14f31. Report an issue: GitHub.