canopy-network/canopy · error · PluginError

1

1

Error message

plugin or config not initialized

What it means

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').

Source

Thrown at plugin/python/contract/contract.py:174

    ):
        self.config = config
        self.fsm_config = fsm_config
        self.plugin = plugin
        self.fsm_id = fsm_id

    def genesis(self, request: PluginGenesisRequest) -> PluginGenesisResponse:
        """Genesis implements logic to import a json file to create the state at height 0."""
        return PluginGenesisResponse()

    def begin_block(self, request: PluginBeginRequest) -> PluginBeginResponse:
        """BeginBlock is code that is executed at the start of applying the block."""
        return PluginBeginResponse()

    async def check_tx(self, request: PluginCheckRequest) -> PluginCheckResponse:
        """CheckTx is code that is executed to statelessly validate a transaction."""
        try:
            if not self.plugin or not self.config:
                raise PluginError(1, "plugin", "plugin or config not initialized")

            # Validate fee - read fee params from state
            resp = await self.plugin.state_read(
                self,
                PluginStateReadRequest(
                    keys=[PluginKeyRead(query_id=random.randint(0, 2**53), key=key_for_fee_params())]
                ),
            )

            if resp.HasField("error"):
                response = PluginCheckResponse()
                response.error.CopyFrom(resp.error)
                return response

            # Convert bytes into fee parameters
            if not resp.results or not resp.results[0].entries:
                raise PluginError(1, "plugin", "Fee parameters not found")

View on GitHub (pinned to ee8197d91d)

Solutions

  1. 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.
  2. Confirm config.json has the correct 'plugin' setting and DataDirPath matching the running node, then restart both node and plugin.
  3. In tests, initialize Contract with a real or stubbed plugin and config before calling check_tx, or skip check_tx entirely.
  4. Add startup logging/assertions after handshake to fail fast if config is not populated before serving requests.

Example fix

// before (test)
contract = Contract()
resp = await contract.check_tx(req)  # PluginError 1
// after
contract = Contract(plugin=stub_plugin, config=Config(chain_id=1))
resp = await contract.check_tx(req)
Defensive patterns

Strategy: try-catch

Validate before calling

if contract.plugin is None or contract.config is None:
    raise RuntimeError('Contract not initialized: handshake incomplete; cannot call check_tx')

Type guard

def contract_ready(c) -> bool:
    return getattr(c, 'plugin', None) is not None and getattr(c, 'config', None) is not None

Try / catch

try:
    resp = await contract.check_tx(req)
except PluginError as e:
    if e.code == 1 and 'not initialized' in e.msg:
        logger.error('plugin handshake incomplete; check socket and config')
    return PluginCheckResponse(error=e)

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


AI-assisted analysis of canopy-network/canopy@ee8197d91d (2026-09-06). Data as JSON: /api/errors/8547cc40c8448101. Report an issue: GitHub.