{"record":{"id":"3dc77ae2bd7c2509","repo":"pinpoint-apm/pinpoint","slug":"corrupted-schema-change-logs-duplicate-order-for","errorCode":null,"errorMessage":"Corrupted schema change logs. Duplicate order for change set : ","messagePattern":"Corrupted schema change logs\\. Duplicate order for change set : ","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"critical","filePath":"hbase/hbase-schema/src/main/java/com/navercorp/pinpoint/hbase/schema/service/SchemaChangeLogServiceImpl.java","lineNumber":121,"sourceCode":"                .execOrder(executionOrder)\n                .checkSum(checkSum)\n                .value(changeSet.getValue())\n                .build();\n        schemaChangeLogDao.insertChangeLog(namespace, schemaChangeLog);\n        return schemaChangeLog;\n    }\n\n    @Override\n    public List<SchemaChangeLog> getSchemaChangeLogs(String namespace) {\n        List<SchemaChangeLog> schemaChangeLogs = schemaChangeLogDao.getChangeLogs(namespace);\n        Map<Integer, SchemaChangeLog> orderedSchemaChangeLogs = new TreeMap<>();\n        Set<String> schemaChangeLogIds = new HashSet<>();\n        for (SchemaChangeLog schemaChangeLog : schemaChangeLogs) {\n            Integer execOrder = schemaChangeLog.getExecOrder();\n            String id = schemaChangeLog.getId();\n            SchemaChangeLog previousLog = orderedSchemaChangeLogs.put(execOrder, schemaChangeLog);\n            if (previousLog != null) {\n                throw new IllegalStateException(\"Corrupted schema change logs. Duplicate order for change set : \" + id);\n            }\n            if (!schemaChangeLogIds.add(schemaChangeLog.getId())) {\n                throw new IllegalStateException(\"Corrupted schema change logs. Duplicate change set : \" + id);\n            }\n        }\n        return new ArrayList<>(orderedSchemaChangeLogs.values());\n    }\n\n    @Override\n    public SchemaChangeLog getSchemaChangeLog(String namespace, String id) {\n        Assert.hasLength(id, \"namespace must not be empty\");\n        return schemaChangeLogDao.getChangeLog(namespace, id);\n    }\n\n}\n","sourceCodeStart":103,"sourceCodeEnd":137,"githubUrl":"https://github.com/pinpoint-apm/pinpoint/blob/744c3d3075e595656abb1ae331ad2c0e4c9eb996/hbase/hbase-schema/src/main/java/com/navercorp/pinpoint/hbase/schema/service/SchemaChangeLogServiceImpl.java#L103-L137","documentation":"Thrown by SchemaChangeLogServiceImpl.getSchemaChangeLogs when two stored change log records carry the same execOrder value. Records are ordered by execOrder (orderedSchemaChangeLogs.put returns a previous entry), and a collision means the log table content is corrupted since each change set must have a distinct execution order. Reading logs is aborted rather than returning an ambiguous ordering.","triggerScenarios":"Reading change logs where two rows in the schema change log table share an identical execOrder column value.","commonSituations":"Concurrent schema updates on multiple nodes writing logs without proper locking/ordering; manual edits or partial backup restores of the log table; a bug or race in an older writer version that assigned the same order twice.","solutions":["Identify the duplicate rows (SELECT id, execOrder ORDER BY execOrder) and fix/remove the corrupt record so orders are unique and contiguous.","Restore the change log table from a known-good backup taken before the corruption.","Ensure only one node/process performs schema updates at a time (distributed lock) to prevent concurrent writers from colliding.","If corruption cannot be repaired safely, back up data, drop managed tables and the log table, and re-initialize."],"exampleFix":"// before: two rows with execOrder=3\n// after: renumber duplicates\nUPDATE schema_change_log SET execOrder = 4 WHERE id = 'changeSet-7';","handlingStrategy":"try-catch","validationCode":"// Detect duplicates in the log table before processing\nMap<Integer, Long> byOrder = logs.stream()\n    .collect(Collectors.groupingBy(SchemaChangeLog::getExecOrder, Collectors.counting()));\nboolean corrupt = byOrder.values().stream().anyMatch(c -> c > 1);","typeGuard":null,"tryCatchPattern":"try { logs = schemaChangeLogService.getSchemaChangeLogs(namespace); } catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"Duplicate order\")) { alertOps(\"Corrupt change log: execOrder collision\"); }\n}","preventionTips":["Serialize schema updates with a distributed lock","Make log writes idempotent keyed on changeSet id","Back up the change log table before any restore","Monitor for concurrent updater processes"],"tags":["hbase","data-corruption","duplicate-key"],"backgroundTag":"internal-invariant-violation","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"}