{"record":{"id":"41090ef1d8903005","repo":"OtterMind/Chat2DB","slug":"diff-error","errorCode":"diff_error","errorMessage":"diff_error","messagePattern":"diff_error","errorType":"exception","errorClass":"BusinessException","httpStatus":null,"severity":"error","filePath":"chat2db-community-server/chat2db-community-domain/chat2db-community-domain-core/src/main/java/ai/chat2db/community/domain/core/impl/db/DbDiffServiceImpl.java","lineNumber":99,"sourceCode":"\n            if (!FileUtil.exist(path)) {\n                return \"-- No differences. \";\n            }\n            configureLiquibaseTrackingTables(targetDatabase, databaseChangeLogTableName, databaseChangeLogLockTableName);\n            String diffOutput = executeLiquibaseUpdate(targetDatabase, resourceAccessor, stringWriter);\n            String filteredOutput = filter(diffOutput, target.getDbType(), databaseChangeLogTableName, databaseChangeLogLockTableName);\n\n            if (StringUtils.isBlank(filteredOutput)) {\n                log.error(\"diff error, filteredOutput is empty:\" + source.getDatabaseName() + \":\" + source.getSchemaName() + \",\" + target.getDatabaseName() + \":\" + target.getSchemaName());\n                log.error(\"diff xml:\" + FileUtil.readUtf8String(filePath + File.separator + DIFF_FILE));\n            }\n            return filteredOutput;\n        } catch (Exception e) {\n            log.error(\"diff error\", e);\n            if (FileUtil.exist(filePath + File.separator + DIFF_FILE)) {\n                log.error(\"diff xml:\" + FileUtil.readUtf8String(filePath + File.separator + DIFF_FILE));\n            }\n            throw new BusinessException(\"diff_error\", new Object[]{e.getMessage()}, e);\n        } finally {\n            try {\n                FileUtil.del(filePath);\n            } catch (Exception e) { // impl-contract: best-effort - cleanup failure must not hide the diff result or original failure.\n                log.error(\"delete file error\", e);\n            }\n        }\n    }\n\n    private ConnectInfo buildConnectInfo(DbConnectionDiffRequest param) {\n        WorkspaceDataSource dataSource = workspaceDataSourceService.queryDisplayDataSourceById(param.getDataSourceId(), true);\n        if (dataSource == null) {\n            throw new BusinessException(\"datasource.not.found\");\n        }\n        return connectionContextConverter.datasource2connectInfo(param, dataSource,\n                JdbcUrlUtils.resetUrl(dataSource.getUrl(), dataSource.getType(), dataSource.getServiceType()));\n    }\n","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/OtterMind/Chat2DB/blob/5ee1e990e73fbcae1969dc554be254fedb3ab888/chat2db-community-server/chat2db-community-domain/chat2db-community-domain-core/src/main/java/ai/chat2db/community/domain/core/impl/db/DbDiffServiceImpl.java#L81-L117","documentation":"Thrown by the diff() method's catch-all when any exception occurs during the Liquibase schema-diff workflow — building connections, initializing Liquibase Database objects, generating DiffResult, writing the changelog, or executing the Liquibase update. The original exception's message is passed as the first argument and the exception is chained. This is a wrapper error; the root cause is in the chained exception and the logged diff XML.","triggerScenarios":"Any uncaught exception inside the try-with-resources block of diff(): LiquibaseException from DiffGeneratorFactory.compare, DatabaseException from DatabaseFactory initialization, IOException from changelog file I/O, SQL errors from Liquibase update execution, or parser errors during filter().","commonSituations":"Unsupported dialect for Liquibase diff; schema/catalog mismatch between source and target; connection authentication or network failure mid-diff; incompatible Liquibase version; permissions to create tracking tables missing on target.","solutions":["Inspect the chained exception (BusinessException.getCause()) and the logged 'diff xml' for the root cause.","Verify both source and target datasources are reachable and the dbTypes are supported by the bundled Liquibase.","Ensure the target database user has CREATE TABLE permission (Liquibase creates tracking tables).","Check that schemaName/databaseName in the request are valid for both connections."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    String changeLog = diffService.diff(sourceReq, targetReq);\n} catch (BusinessException e) {\n    if (\"diff_error\".equals(e.getCode())) {\n        Throwable root = e.getCause();\n        // inspect root (LiquibaseException / DatabaseException / IOException)\n        // surface root.getMessage() to the user\n    } else { throw e; }\n}","preventionTips":["Verify both datasource connections independently before running diff.","Ensure the target DB user has DDL/tracking-table permissions.","Test Liquibase compatibility with both dialects before relying on diff."],"tags":["diff","liquibase","wrapper-error"],"backgroundTag":null,"analyzedSha":"5ee1e990e73fbcae1969dc554be254fedb3ab888","analyzedAt":"2026-08-14T07:05:03.077Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}