tracel-ai/burn · critical

Invalid response type for ReadTensor

Error message

Invalid response type for ReadTensor

What it means

In burn-remote, `read_tensor_async` submits a tensor-read request to the remote service and awaits a response on a oneshot channel. The protocol contract is that the reply carries `TaskResponseContent::ReadTensor`; if the server/channel delivers any other task-response variant, the client panics with this message. It indicates a client/server protocol desynchronization or a mismatched response routing, not a tensor data error (genuine transport failures come back as `ExecutionError::Generic` on the Err branch).

Source

Thrown at crates/burn-remote/src/client/runner.rs:47

        self.handle.submit(move |s| s.register_op(stream_id, op));
    }

    fn read_tensor_async(
        &self,
        tensor: burn_ir::TensorIr,
    ) -> DynFut<Result<TensorData, ExecutionError>> {
        // Issue the request synchronously so ordering is preserved relative to subsequent
        // submissions; the returned future just awaits the server's response.
        let stream_id = StreamId::current();
        let rx = self
            .handle
            .submit_blocking(move |s| s.read_tensor(stream_id, tensor))
            .expect("Service call failed");

        Box::pin(async move {
            match rx.await {
                Ok(TaskResponseContent::ReadTensor(res)) => res,
                Ok(_) => panic!("Invalid response type for ReadTensor"),
                Err(e) => Err(ExecutionError::Generic {
                    reason: format!("Failed to read tensor: {e:?}"),
                    backtrace: BackTrace::capture(),
                }),
            }
        })
    }

    fn register_tensor_data(&self, data: TensorData) -> RouterTensor<Self> {
        let shape = data.shape.clone();
        let dtype = data.dtype;
        let id = service::new_tensor_id();

        // Fire-and-forget: the outgoing batch flushes itself once buffered data bytes (or the task
        // count) cross their threshold — see `OutgoingBatch` — so no explicit flush is needed here.
        let stream_id = StreamId::current();
        self.handle
            .submit(move |s| s.register_tensor(stream_id, id, data));

View on GitHub (pinned to d16f7ba2ed)

Solutions

  1. Rebuild and redeploy client and server from the same burn version so the TaskResponseContent wire protocol matches.
  2. Verify no custom/forked service code routes responses to the wrong stream id for read_tensor requests.
  3. Update to the latest burn release; if it persists, file a bug with a minimal repro (remote backend, read a tensor after a couple of ops).

Example fix

// before: client 0.x talking to server 0.y (protocol skew) -> panic
// after: pin the same burn version on both sides
# Cargo.toml (client and server)
[dependencies]
burn = { version = "=0.18.0", features = ["remote"] }
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure client and server report the same burn version before exchanging tensors
assert_eq!(client.protocol_version(), server.protocol_version());

Type guard

match response {
    TaskResponseContent::ReadTensor(res) => Ok(res),
    other => Err(format!("unexpected response variant: {other:?}")),
}

Try / catch

// panic! cannot be caught in stable Rust without catch_unwind
let result = std::panic::catch_unwind(AssertUnwindSafe(|| tensor.into_data()));
match result {
    Ok(data) => { /* use data */ }
    Err(_) => { /* reconnect with matching versions */ }
}

Prevention

When it happens

Trigger: Calling `.into_data()`/`to_data()` (which routes through RouterClient::read_tensor_async) on a tensor owned by a RemoteClient when the oneshot `rx` resolves with a TaskResponseContent variant other than ReadTensor — i.e. the response queued for this stream id belongs to a different task.

Common situations: Client/server version skew where response variants were reordered or remapped between burn versions; running mismatched burn-remote client and server binaries; stream id reuse/collision after sync; custom or forked server code replying with the wrong TaskResponseContent.

Related errors


AI-assisted analysis of tracel-ai/burn@d16f7ba2ed (2026-09-05). Data as JSON: /api/errors/bfe8113a5bd12aec. Report an issue: GitHub.