{"record":{"id":"1170417cf7b96182","repo":"pinpoint-apm/pinpoint","slug":"duplicate-changeset-found-id","errorCode":null,"errorMessage":"Duplicate changeSet found. Id: ","messagePattern":"Duplicate changeSet found\\. Id: ","errorType":"validation","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"hbase/hbase-schema/src/main/java/com/navercorp/pinpoint/hbase/schema/reader/xml/XmlParseContext.java","lineNumber":67,"sourceCode":"    }\n\n    void setResource(Resource resource) {\n        this.resource = Objects.requireNonNull(resource, \"resource\");\n        if (visitedResources.contains(resource)) {\n            throw new IllegalStateException(\"Cyclic include detected for : \" + resource);\n        }\n        visitedResources.add(resource);\n    }\n\n    void addChangeSets(Collection<ChangeSet> changeSets) {\n        if (CollectionUtils.isEmpty(changeSets)) {\n            return;\n        }\n        for (ChangeSet changeSet : changeSets) {\n            String changeSetId = changeSet.getId();\n            ChangeSet previous = changeSetMap.put(changeSetId, changeSet);\n            if (previous != null) {\n                throw new IllegalStateException(\"Duplicate changeSet found. Id: \" + changeSetId);\n            }\n        }\n    }\n\n    List<ChangeSet> getChangeSets() {\n        return new ArrayList<>(changeSetMap.values());\n    }\n}\n","sourceCodeStart":49,"sourceCodeEnd":76,"githubUrl":"https://github.com/pinpoint-apm/pinpoint/blob/744c3d3075e595656abb1ae331ad2c0e4c9eb996/hbase/hbase-schema/src/main/java/com/navercorp/pinpoint/hbase/schema/reader/xml/XmlParseContext.java#L49-L76","documentation":"XmlParseContext.addChangeSets keys change sets by id in changeSetMap; if two change sets share the same id, put returns the previous entry and an IllegalStateException is thrown. Change set ids must be unique because they are used for checksum/version tracking of applied schema changes.","triggerScenarios":"Two <changeSet> elements with the same id attribute across the schema XML (including files pulled in via <include>), passed to addChangeSets.","commonSituations":"Copy-pasting a changeSet block and forgetting to change the id; two included XML files each defining a changeSet with the same id; merging schema files from branches without deduplicating ids.","solutions":["Rename one of the duplicate changeSet ids to a unique value","Search all schema XML (and includes) for the offending id and deduplicate","Adopt an id convention (e.g. date+table+seq) to avoid collisions across files","If the duplicate is from a stale branch merge, resolve the schema XML merge conflicts properly"],"exampleFix":"// before\n<changeSet id=\"create-agent-table\">...\n<changeSet id=\"create-agent-table\">...\n// after\n<changeSet id=\"create-agent-table\">...\n<changeSet id=\"create-agent-table-v2\">...","handlingStrategy":"validation","validationCode":"Set<String> ids = new HashSet<>();\nfor (ChangeSet cs : allChangeSets) {\n    if (!ids.add(cs.getId())) {\n        throw new IllegalStateException(\"Duplicate changeSet id: \" + cs.getId());\n    }\n}","typeGuard":null,"tryCatchPattern":"try {\n    schemaReader.loadChangeSets(resource);\n} catch (IllegalStateException e) {\n    if (e.getMessage().startsWith(\"Duplicate changeSet found\")) {\n        // locate and rename the duplicated id across schema XML\n    } else {\n        throw e;\n    }\n}","preventionTips":["Grep all schema XML for id=\" duplicates before release","Use unique, descriptive ids (table + operation + sequence)","Include files can carry duplicates too — validate the merged set, not just single files"],"tags":["hbase","xml","duplicate-id","schema"],"backgroundTag":"duplicate-identifier","analyzedSha":"744c3d3075e595656abb1ae331ad2c0e4c9eb996","analyzedAt":"2026-09-07T18:48:45.289Z","contentChangedAt":"2026-09-07T18:48:45.289Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}