pinpoint-apm/pinpoint · error · IllegalStateException
Cyclic include detected for :
Error message
Cyclic include detected for :
What it means
XmlParseContext.setResource detects recursive <include> chains in the schema XML: if the resource being loaded is already in visitedResources, an IllegalStateException is thrown. Without this guard, cyclic includes would loop forever loading the same files.
Source
Thrown at hbase/hbase-schema/src/main/java/com/navercorp/pinpoint/hbase/schema/reader/xml/XmlParseContext.java:54
private final Map<String, ChangeSet> changeSetMap = new LinkedHashMap<>();
private final Set<Resource> visitedResources = new HashSet<>();
private Resource resource;
XmlParseContext(Resource resource) {
this.resource = Objects.requireNonNull(resource, "resource");
}
Resource getResource() {
return resource;
}
void setResource(Resource resource) {
this.resource = Objects.requireNonNull(resource, "resource");
if (visitedResources.contains(resource)) {
throw new IllegalStateException("Cyclic include detected for : " + resource);
}
visitedResources.add(resource);
}
void addChangeSets(Collection<ChangeSet> changeSets) {
if (CollectionUtils.isEmpty(changeSets)) {
return;
}
for (ChangeSet changeSet : changeSets) {
String changeSetId = changeSet.getId();
ChangeSet previous = changeSetMap.put(changeSetId, changeSet);
if (previous != null) {
throw new IllegalStateException("Duplicate changeSet found. Id: " + changeSetId);
}
}
}
List<ChangeSet> getChangeSets() {View on GitHub (pinned to 744c3d3075)
Solutions
- Inspect the resource chain (from the message and stack trace) and remove the include that closes the cycle
- Remove the self-include if a file includes itself
- Restructure shared definitions into a common file included exactly once per branch
- If a file legitimately needs to be included in multiple places, ensure it is not re-included within its own subtree
Example fix
// before (a.xml) <include file="b.xml"/> <!-- and b.xml includes a.xml --> // after (b.xml) <!-- remove the include of a.xml -->
Defensive patterns
Strategy: try-catch
Validate before calling
// detect cycles before loading by tracking includes yourself
Set<String> seen = new HashSet<>();
for (String include : collectIncludes(rootXml)) {
if (!seen.add(include)) throw new IllegalStateException("cycle at " + include);
} Try / catch
try {
schemaReader.loadChangeSets(resource);
} catch (IllegalStateException e) {
if (e.getMessage().startsWith("Cyclic include detected")) {
// fix the include chain in the offending XML file
} else {
throw e;
}
} Prevention
- Draw the include graph of schema files and verify it is a DAG
- Never include a file within its own subtree
- Centralize shared change sets in one file included once per entry point
When it happens
Trigger: Schema XML file A includes file B, and B (directly or transitively) includes A again; loadChangeSets then calls setResource with a Resource already visited.
Common situations: Copy-pasting include lines so a file includes itself; refactoring schema files and accidentally creating an A->B->A cycle; symlinked resources that resolve to the same file under different paths (if Resource equality matches).
Related errors
- Duplicate changeSet found. Id:
- Cannot add an existing column family :
- splitKeys must not be empty
- numRegions must be greater than 1
- Error loading change sets from
AI-assisted analysis of pinpoint-apm/pinpoint@744c3d3075 (2026-09-07).
Data as JSON: /api/errors/d491d0fe8b14e227.
Report an issue: GitHub.