{"record":{"id":"8547cc40c8448101","repo":"canopy-network/canopy","slug":"1","errorCode":"1","errorMessage":"plugin or config not initialized","messagePattern":"plugin or config not initialized","errorType":"exception","errorClass":"PluginError","httpStatus":null,"severity":"error","filePath":"plugin/python/contract/contract.py","lineNumber":174,"sourceCode":"    ):\n        self.config = config\n        self.fsm_config = fsm_config\n        self.plugin = plugin\n        self.fsm_id = fsm_id\n\n    def genesis(self, request: PluginGenesisRequest) -> PluginGenesisResponse:\n        \"\"\"Genesis implements logic to import a json file to create the state at height 0.\"\"\"\n        return PluginGenesisResponse()\n\n    def begin_block(self, request: PluginBeginRequest) -> PluginBeginResponse:\n        \"\"\"BeginBlock is code that is executed at the start of applying the block.\"\"\"\n        return PluginBeginResponse()\n\n    async def check_tx(self, request: PluginCheckRequest) -> PluginCheckResponse:\n        \"\"\"CheckTx is code that is executed to statelessly validate a transaction.\"\"\"\n        try:\n            if not self.plugin or not self.config:\n                raise PluginError(1, \"plugin\", \"plugin or config not initialized\")\n\n            # Validate fee - read fee params from state\n            resp = await self.plugin.state_read(\n                self,\n                PluginStateReadRequest(\n                    keys=[PluginKeyRead(query_id=random.randint(0, 2**53), key=key_for_fee_params())]\n                ),\n            )\n\n            if resp.HasField(\"error\"):\n                response = PluginCheckResponse()\n                response.error.CopyFrom(resp.error)\n                return response\n\n            # Convert bytes into fee parameters\n            if not resp.results or not resp.results[0].entries:\n                raise PluginError(1, \"plugin\", \"Fee parameters not found\")\n","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/canopy-network/canopy/blob/ee8197d91dd410f6592cb650a94c925ee6dc8bad/plugin/python/contract/contract.py#L156-L192","documentation":"check_tx statelessly validates transactions, but it first needs an initialized plugin connection and config (received during handshake). If self.plugin or self.config is unset — meaning the handshake with the FSM never completed or the Contract was constructed standalone — it raises PluginError(1, 'plugin', 'plugin or config not initialized').","triggerScenarios":"The FSM sends a CheckTx request before (or without) a successful handshake that populates plugin and config; running the Contract directly in tests without establishing the socket connection; the handshake failed silently (bad socket path, FSM rejected config).","commonSituations":"Pointing the plugin at the wrong data dir so plugin.sock never connects; config.json plugin settings changed so handshake fails; unit tests instantiating Contract and calling check_tx without wiring a Plugin instance.","solutions":["Verify the plugin process connected and completed the handshake before traffic: check that DataDirPath/plugin.sock exists and the FSM logs a successful plugin registration.","Confirm config.json has the correct 'plugin' setting and DataDirPath matching the running node, then restart both node and plugin.","In tests, initialize Contract with a real or stubbed plugin and config before calling check_tx, or skip check_tx entirely.","Add startup logging/assertions after handshake to fail fast if config is not populated before serving requests."],"exampleFix":"// before (test)\ncontract = Contract()\nresp = await contract.check_tx(req)  # PluginError 1\n// after\ncontract = Contract(plugin=stub_plugin, config=Config(chain_id=1))\nresp = await contract.check_tx(req)","handlingStrategy":"try-catch","validationCode":"if contract.plugin is None or contract.config is None:\n    raise RuntimeError('Contract not initialized: handshake incomplete; cannot call check_tx')","typeGuard":"def contract_ready(c) -> bool:\n    return getattr(c, 'plugin', None) is not None and getattr(c, 'config', None) is not None","tryCatchPattern":"try:\n    resp = await contract.check_tx(req)\nexcept PluginError as e:\n    if e.code == 1 and 'not initialized' in e.msg:\n        logger.error('plugin handshake incomplete; check socket and config')\n    return PluginCheckResponse(error=e)","preventionTips":["Confirm plugin.sock exists and the handshake completed before serving requests.","Match the plugin's DataDirPath with the node's config.json.","Restart node and plugin together after config changes.","In tests, always initialize plugin/config stubs before calling contract methods."],"tags":["python","plugin-lifecycle","initialization","state-machine"],"backgroundTag":"module-init-failed","analyzedSha":"ee8197d91dd410f6592cb650a94c925ee6dc8bad","analyzedAt":"2026-09-06T09:30:15.973Z","contentChangedAt":"2026-09-06T09:30:15.973Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}