canopy-network/canopy · error · kotlin.Exception

No response received for id $requestId

Error message

No response received for id $requestId

What it means

Thrown in PluginClient.sendSync after the response latch fires but pendingResponse.response is still null — the await succeeded without a response being stored. This is a signaling/race defect or an empty reply frame, meaning the FSM's reply never materialized into a usable message.

Source

Thrown at plugin/kotlin/src/main/kotlin/com/canopy/plugin/PluginClient.kt:320

        lock.withLock {
            pending[requestId] = pendingResponse
            if (contract != null) {
                requestContract[requestId] = contract
            }
        }

        sendMessage(msg)

        // Wait for response with timeout
        if (!pendingResponse.lock.await(TIMEOUT_SECONDS, TimeUnit.SECONDS)) {
            lock.withLock {
                pending.remove(requestId)
                requestContract.remove(requestId)
            }
            throw Exception("Request timeout for id $requestId")
        }

        return pendingResponse.response ?: throw Exception("No response received for id $requestId")
    }

    /**
     * Send response to FSM
     */
    private fun sendResponse(id: Long, builder: PluginToFSM.Builder) {
        val msg = builder.setId(id).build()
        sendMessage(msg)
    }

    /**
     * Send protobuf message with length prefix
     */
    private fun sendMessage(msg: PluginToFSM) {
        val bytes = msg.toByteArray()
        val lengthPrefix = ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN).putInt(bytes.size).array()

        lock.withLock {

View on GitHub (pinned to ee8197d91d)

Solutions

  1. Inspect the inbound message loop to confirm every completed PendingResponse is fulfilled with a response.
  2. Check for a race between latch completion and response assignment in the listener thread.
  3. Retry the request; persistent occurrences indicate a bug in the reply dispatch path rather than a network issue.
Defensive patterns

Strategy: try-catch

When it happens

Trigger: Thrown at plugin/kotlin/src/main/kotlin/com/canopy/plugin/PluginClient.kt:320 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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