{"record":{"id":"d22c9e3be5c8235f","repo":"pinpoint-apm/pinpoint","slug":"current-table-schema-does-not-match-the-schema-cha","errorCode":null,"errorMessage":"Current table schema does not match the schema change log records.","messagePattern":"Current table schema does not match the schema change log records\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"critical","filePath":"hbase/hbase-schema/src/main/java/com/navercorp/pinpoint/hbase/schema/service/HbaseSchemaServiceImpl.java","lineNumber":211,"sourceCode":"    }\n\n    private boolean updateExistingSchemas(String namespace, String compression, List<ChangeSet> changeSets, List<TableDescriptor> currentHtds, List<SchemaChangeLog> executedLogs) {\n        logger.info(\"[{}] Updating hbase schema.\", namespace);\n\n        List<String> executedChangeLogIds = executedLogs.stream()\n                .map(SchemaChangeLog::getId).collect(Collectors.toList());\n        logger.info(\"[{}] Executed change logs : {}\", namespace, executedChangeLogIds);\n\n        ChangeSetManager changeSetManager = new ChangeSetManager(changeSets);\n\n        // Check if the current table schema matches the expected schema specified by the executed schema change logs.\n        HbaseSchemaCommandManager initCommandManager = new HbaseSchemaCommandManager(namespace, compression);\n        List<ChangeSet> executedChangeSets = changeSetManager.getExecutedChangeSets(executedLogs);\n        for (ChangeSet executedChangeSet : executedChangeSets) {\n            initCommandManager.applyChangeSet(executedChangeSet);\n        }\n        if (!hbaseSchemaVerifier.verifySchemas(initCommandManager.getSchemaSnapshot(), currentHtds)) {\n            throw new IllegalStateException(\"Current table schema does not match the schema change log records.\");\n        }\n\n        List<ChangeSet> changeSetsToApply = changeSetManager.filterExecutedChangeSets(executedLogs);\n        if (changeSetsToApply.isEmpty()) {\n            logger.info(\"[{}] Hbase schema already at latest version\", namespace);\n            return false;\n        }\n        HbaseSchemaCommandManager updateCommandManager = new HbaseSchemaCommandManager(namespace, compression, currentHtds);\n        return applyChangeSets(updateCommandManager, changeSetsToApply, executedLogs);\n    }\n\n\n    private boolean applyChangeSets(HbaseSchemaCommandManager commandManager, List<ChangeSet> changeSets, List<SchemaChangeLog> executedLogs) {\n        if (CollectionUtils.isEmpty(changeSets)) {\n            return false;\n        }\n\n        String namespace = commandManager.getNamespace();","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/pinpoint-apm/pinpoint/blob/744c3d3075e595656abb1ae331ad2c0e4c9eb996/hbase/hbase-schema/src/main/java/com/navercorp/pinpoint/hbase/schema/service/HbaseSchemaServiceImpl.java#L193-L229","documentation":"Thrown by HbaseSchemaServiceImpl.updateExistingSchemas when replaying all previously executed change sets against an empty namespace produces a table layout (schema snapshot) that does not match the live HBase table descriptors (currentHtds). It means the change log history and the actual table schemas have diverged — someone altered tables manually, or logs were lost/corrupted. Update is aborted to prevent applying further changes on an inconsistent base.","triggerScenarios":"Calling update() when the schema change log table has records, but HbaseSchemaVerifier.verifySchemas fails after rebuilding the snapshot from executedChangeSets vs the current HTableDescriptors fetched from HBase.","commonSituations":"An admin manually created/modified/dropped tables or column families in HBase outside of the schema tooling; the change log table was partially restored from a backup; a changeSet was edited after it was already executed (history no longer reproduces reality); namespace mismatch pointing update at another cluster's tables.","solutions":["Compare the current table descriptors with the replayed snapshot (hbase shell 'list' / describe) and revert manual table modifications so they match the change log.","If change sets were edited after execution, restore the original definitions that were actually executed.","As a last resort for a corrupted history, back up data, drop the schema change log table and the managed tables, and re-initialize from scratch (fresh initialization).","Ensure the configured namespace/cluster is the intended one before re-running update()."],"exampleFix":"// before: silently ignoring mismatch\n// after: detect drift early in a health check\nSchemaSnapshot snapshot = initCommandManager.getSchemaSnapshot();\nif (!hbaseSchemaVerifier.verifySchemas(snapshot, currentHtds)) {\n    logger.error(\"Schema drift detected for namespace {}. Tables: {}\", namespace, currentHtds.keySet());\n    throw new IllegalStateException(\"...\" );\n}","handlingStrategy":"try-catch","validationCode":"// Prohibit manual table changes and verify drift regularly\nif (!hbaseSchemaVerifier.verifySchemas(snapshot, currentHtds)) {\n    alert(\"Schema drift detected for namespace \" + namespace);\n}","typeGuard":null,"tryCatchPattern":"try { schemaService.update(); } catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"does not match the schema change log\")) {\n        // page an admin: manual table drift or corrupted history\n    }\n}","preventionTips":["Change tables only through the schema tooling, never manually in hbase shell","Never edit a changeSet after it has been executed","Take a backup of the change log table before restores","Pin namespace/cluster configuration"],"tags":["hbase","state-mismatch","schema-drift"],"backgroundTag":"invalid-state-transition","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"}