apache/shardingsphere · critical · IllegalStateException
Duplicate rule tag `!%s` in file `%s`
Error message
Duplicate rule tag `!%s` in file `%s`
What it means
Thrown by ProxyConfigurationLoader.checkDuplicateRule when a single database YAML file declares two or more rule configurations of the same type (same !<TAG> rule tag). The loader groups YamlRuleConfiguration swapper targets by rule configuration class and counts; any count > 1 aborts startup with IllegalStateException naming the duplicated tag and file. It prevents ambiguous rule sets where later entries would silently override earlier ones.
Source
Thrown at proxy/backend/core/src/main/java/org/apache/shardingsphere/proxy/backend/config/ProxyConfigurationLoader.java:179
YamlProxyDatabaseConfiguration result = YamlEngine.unmarshal(yamlFile, YamlProxyDatabaseConfiguration.class);
if (result.isEmpty()) {
return Optional.empty();
}
Preconditions.checkNotNull(result.getDatabaseName(), "Property `databaseName` in file `%s` is required.", yamlFile.getName());
DatabaseNameValidator.validate(result.getDatabaseName());
checkDuplicateRule(result.getRules(), yamlFile);
return Optional.of(result);
}
private static void checkDuplicateRule(final Collection<YamlRuleConfiguration> ruleConfigs, final File yamlFile) {
if (ruleConfigs.isEmpty()) {
return;
}
Map<Class<? extends RuleConfiguration>, Long> ruleConfigTypeCountMap = ruleConfigs.stream()
.collect(Collectors.groupingBy(YamlRuleConfiguration::getRuleConfigurationType, Collectors.counting()));
Optional<Entry<Class<? extends RuleConfiguration>, Long>> duplicateRuleConfig = ruleConfigTypeCountMap.entrySet().stream().filter(each -> each.getValue() > 1L).findFirst();
if (duplicateRuleConfig.isPresent()) {
throw new IllegalStateException(String.format("Duplicate rule tag `!%s` in file `%s`", getDuplicateRuleTagName(duplicateRuleConfig.get().getKey()), yamlFile.getName()));
}
}
@SuppressWarnings("rawtypes")
private static Object getDuplicateRuleTagName(final Class<? extends RuleConfiguration> ruleConfigClass) {
Optional<YamlRuleConfigurationSwapper> result = ShardingSphereServiceLoader.getServiceInstances(YamlRuleConfigurationSwapper.class)
.stream().filter(each -> ruleConfigClass.equals(each.getTypeClass())).findFirst();
return result.orElseThrow(() -> new IllegalStateException("Not find rule tag name of class " + ruleConfigClass));
}
private static File[] findRuleConfigurationFiles(final File path) {
return path.listFiles(each -> DATABASE_CONFIG_FILE_PATTERN.matcher(each.getName()).matches() || COMPATIBLE_DATABASE_CONFIG_FILE_PATTERN.matcher(each.getName()).matches());
}
}
View on GitHub (pinned to e952770a21)
Solutions
- Open the named file and merge the two blocks with the same rule tag into one configuration (combine their tables/rules lists)
- Delete the stale duplicate block if it was left from a copy-paste
- If you need multiple rules of the same feature, put them inside the single tag's collection, not as a second top-level tag
- Validate proxy conf YAML with a duplicate-tag lint before deployment
Example fix
# before (database-xxx.yaml) rules: - !SHARDING tables: ... - !SHARDING tables: [t2] # after rules: - !SHARDING tables: [t1, t2] # merged into one block
Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight: fail fast on duplicate rule tags before proxy startup
YamlConfiguration yaml = loadYaml(file);
Map<String, Long> tagCounts = yaml.getRules().stream()
.collect(Collectors.groupingBy(r -> r.getClass().getSimpleName(), Collectors.counting()));
tagCounts.forEach((tag, n) -> { if (n > 1) throw new IllegalStateException("Duplicate rule tag " + tag + " in " + file); }); Try / catch
try {
ProxyConfigurationLoader.loadConfig(dir);
} catch (IllegalStateException e) {
// message names the duplicated tag + file; merge the two blocks into one and restart
failStartupWithFixHint(e.getMessage());
} Prevention
- One top-level rule tag per feature per database YAML; put multiple rules inside that block
- Lint proxy conf/ for duplicate tags in CI before deploy
- Never concatenate two config files blindly during migration; merge their rules lists
When it happens
Trigger: A database-*.yaml containing e.g. two !SHARDING blocks (or two !ENCRYPT blocks) — the YAML snakeyaml tag prefix '!SHARDING' instantiates the same YamlRuleConfiguration class twice, so getRuleConfigurationType counts collide and the Optional<Entry> filter finds the duplicate.
Common situations: Hand-merging config files during migration to standalone mode (concatenating two files end-to-end duplicates the tag); copy-pasting an encrypt/sharding block as a template and forgetting to change its type; repo-managed conf under proxy/conf growing duplicates over time.
Related errors
- PROXY-00001
- 2
- 0
- MCP configuration file `%s` does not exist.
- System property `%s` must be a positive integer, but was `%s
AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14).
Data as JSON: /api/errors/4841f9dac6b4e366.
Report an issue: GitHub.