{"record":{"id":"25fd66dc23068b5b","repo":"canopy-network/canopy","slug":"unexpected-state-write-response","errorCode":null,"errorMessage":"Unexpected state write response","messagePattern":"Unexpected state write response","errorType":"exception","errorClass":"kotlin.Exception","httpStatus":null,"severity":"error","filePath":"plugin/kotlin/src/main/kotlin/com/canopy/plugin/PluginClient.kt","lineNumber":151,"sourceCode":"    }\n\n    /**\n     * Write state to FSM\n     */\n    fun stateWrite(contract: Contract, request: PluginStateWriteRequest): PluginStateWriteResponse {\n        val msg = PluginToFSM.newBuilder()\n            .setId(contract.fsmId)\n            .setStateWrite(request)\n            .build()\n\n        val response = sendSync(contract, msg)\n\n        return when {\n            response.hasStateWrite() -> response.stateWrite\n            response.hasError() -> PluginStateWriteResponse.newBuilder()\n                .setError(response.error)\n                .build()\n            else -> throw Exception(\"Unexpected state write response\")\n        }\n    }\n\n    /**\n     * Execute a detached, read-only state query against Canopy at the given height (0 = latest committed).\n     *\n     * Unlike [stateRead], it is NOT tied to an in-flight tx/block lifecycle and does not require a\n     * Contract context; it allocates its own fresh RANDOM request id, making it safe to call from\n     * custom RPC handlers (e.g. the plugin's own HTTP server).\n     */\n    fun queryState(height: Long, request: PluginStateReadRequest): PluginStateReadResponse {\n        // generate a fresh random request id (not tied to any in-flight FSM request)\n        val requestId = Random.nextLong()\n        val msg = PluginToFSM.newBuilder()\n            .setId(requestId)\n            .setQuery(\n                PluginQueryRequest.newBuilder()\n                    .setHeight(height)","sourceCodeStart":133,"sourceCodeEnd":169,"githubUrl":"https://github.com/canopy-network/canopy/blob/ee8197d91dd410f6592cb650a94c925ee6dc8bad/plugin/kotlin/src/main/kotlin/com/canopy/plugin/PluginClient.kt#L133-L169","documentation":"Thrown in PluginClient.stateWrite when the FSM's response to a state-write request contains neither a stateWrite result nor an error — an unrecognized reply shape. This leaves the write's outcome unknown and indicates protocol desynchronization rather than a rejected write (rejections arrive as an error field).","triggerScenarios":"Thrown at plugin/kotlin/src/main/kotlin/com/canopy/plugin/PluginClient.kt:151 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Verify request id tracking is correct so the pending response matches the state-write request.","Ensure matching proto schemas between plugin and FSM.","Restart the connection/plugin to resynchronize and reissue the write."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"ee8197d91dd410f6592cb650a94c925ee6dc8bad","analyzedAt":"2026-09-06T09:30:15.973Z","contentChangedAt":"2026-09-06T09:30:15.973Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}