tracel-ai/burn · error
Service call failed
Error message
Service call failed
What it means
`read_tensor_async` synchronously submits a `read_tensor` request via `handle.submit_blocking(...)` and unwraps the returned oneshot receiver with `expect("Service call failed")`. If the submission cannot reach the service (runner shut down, channel closed) the call returns `None` and panics. Note the subsequent `rx.await` handles real execution errors as `ExecutionError` — this expect only fires for local service-channel failure.
Source
Thrown at crates/burn-remote/src/client/runner.rs:42
let stream_id = StreamId::current();
// Device ids in the op's payload are *client* remote device ids; rewrite them to
// server-local device indices the server can resolve to its own backend devices. Applies
// to every op — only ops that actually carry device ids are rewritten.
let op = self.resolve_devices(op);
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();
View on GitHub (pinned to d16f7ba2ed)
Solutions
- Recreate the remote client/backend after the service dies, then re-issue the read.
- Keep the service/runner alive until all in-flight tensor reads complete.
- Use `sync`/connection health checks before reads in long-running sessions.
- Catch the panic at a boundary (e.g. `catch_unwind`) if shutdown races are unavoidable, and reconnect.
Example fix
// before let tensor = backend.read_tensor(desc).await; // panics if service dead // after // ensure client is alive or recreate: let backend = get_or_recreate_backend(&config); let tensor = backend.read_tensor(desc).await;
Defensive patterns
Strategy: try-catch
Validate before calling
// guard long sessions: verify connectivity before reads
// e.g. issue a cheap sync/heartbeat; on failure recreate the backend
if !backend_healthy(&handle) { let backend = recreate_backend(&config)?; } Try / catch
let tensor = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
backend_clone.read_tensor(desc)
}));
if tensor.is_err() { /* recreate backend, re-issue read */ } Prevention
- Keep the remote service alive until all reads complete
- Sync and drain pending reads before shutting the client down
- Avoid cloned backends outliving the owning client
- Recreate the backend after any server crash before further reads
When it happens
Trigger: Calling tensor read (via the async backend's `read_tensor`) after the remote service runner has terminated, or submitting on a handle whose channel is closed, so `submit_blocking` returns `None` instead of a response receiver.
Common situations: Reading results after the remote server crashed or connection was torn down; using a client/handle beyond shutdown; WASM suspension killing the service; holding cloned backend past client drop.
Related errors
- Service call failed
- Requires autodiff tensor.
- an enabled float tensor must use an autodiff primitive
- Should be float, got int
- Should be float, got bool
AI-assisted analysis of tracel-ai/burn@d16f7ba2ed (2026-09-05).
Data as JSON: /api/errors/046a9e92b8ad0390.
Report an issue: GitHub.