{"record":{"id":"acea0d2170bce566","repo":"alibaba/canal","slug":"illegal-connection-is-null","errorCode":null,"errorMessage":"illegal connection is null","messagePattern":"illegal connection is null","errorType":"exception","errorClass":"CanalParseException","httpStatus":null,"severity":"error","filePath":"parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/MysqlEventParser.java","lineNumber":139,"sourceCode":"            if (tableMetaTSDB != null && tableMetaTSDB instanceof DatabaseTableMeta) {\n                ((DatabaseTableMeta) tableMetaTSDB).setConnection(metaConnection);\n                ((DatabaseTableMeta) tableMetaTSDB).setFilter(eventFilter);\n                ((DatabaseTableMeta) tableMetaTSDB).setBlackFilter(eventBlackFilter);\n                ((DatabaseTableMeta) tableMetaTSDB).setSnapshotInterval(tsdbSnapshotInterval);\n                ((DatabaseTableMeta) tableMetaTSDB).setSnapshotExpire(tsdbSnapshotExpire);\n                ((DatabaseTableMeta) tableMetaTSDB).init(destination);\n            }\n\n            tableMetaCache = new TableMetaCache(metaConnection, tableMetaTSDB);\n            ((LogEventConvert) binlogParser).setTableMetaCache(tableMetaCache);\n        }\n    }\n\n    protected void afterDump(ErosaConnection connection) {\n        super.afterDump(connection);\n\n        if (connection == null) {\n            throw new CanalParseException(\"illegal connection is null\");\n        }\n\n        if (!(connection instanceof MysqlConnection)) {\n            throw new CanalParseException(\"Unsupported connection type : \" + connection.getClass().getSimpleName());\n        }\n\n        if (metaConnection != null) {\n            try {\n                metaConnection.disconnect();\n            } catch (IOException e) {\n                logger.error(\"ERROR # disconnect meta connection for address:{}\", metaConnection.getConnector()\n                    .getAddress(), e);\n            }\n        }\n    }\n\n    public void start() throws CanalParseException {\n        if (runningInfo == null) { // 第一次链接主库","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/alibaba/canal/blob/87be50e87686a3e8af08c368d0e1ffd1f59eb04a/parse/src/main/java/com/alibaba/otter/canal/parse/inbound/mysql/MysqlEventParser.java#L121-L157","documentation":"MysqlEventParser.afterDump(ErosaConnection) immediately throws CanalParseException(\"illegal connection is null\") if the connection argument is null. This guards the post-dump cleanup path (disconnecting metaConnection) against a null connection that would otherwise NPE on the instanceof check below.","triggerScenarios":"afterDump() is invoked with a null ErosaConnection — typically a lifecycle/bug where the parser's connection was never built or was cleared before cleanup ran.","commonSituations":"A bug in a custom parser subclass overriding buildErosaConnection()/the dump loop; premature stop()/resource clearing racing with afterDump; misconfigured HA failover that nulls the connection mid-cycle.","solutions":["Ensure buildErosaConnection() returns a non-null connection before the dump loop starts.","Avoid nulling the connection field before afterDump completes; order stop()/cleanup after the dump finishes.","If extending MysqlEventParser, do not pass null to super.afterDump()."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if (connection == null) {\n    throw new IllegalArgumentException(\"afterDump called with null connection; check parser lifecycle wiring\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never null the connection field before afterDump runs.","Order stop()/cleanup strictly after the dump loop completes.","In subclasses, always pass the live connection to super.afterDump()."],"tags":["null-check","connection","lifecycle","canal-parse"],"backgroundTag":null,"analyzedSha":"87be50e87686a3e8af08c368d0e1ffd1f59eb04a","analyzedAt":"2026-08-14T04:30:11.918Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}