tracel-ai/burn · info
writer present (checked above)
Error message
writer present (checked above)
What it means
In `Drop for RemoteService`, the code checks `self.writer.is_none()` and returns early, then unwraps the writer with expect; the expect documents that the check above guarantees `Some`. This is a pure internal invariant assertion and unreachable in a stock build — it can only fire if the drop logic itself is altered (e.g. in a fork) or mutated concurrently during teardown.
Source
Thrown at crates/burn-remote/src/client/service.rs:684
return;
}
self.closed = true;
// If we never connected, there's no server-side session to close and no writer to
// drain — whatever was buffered never had a connection to go out on, so just drop it.
if self.writer.is_none() {
return;
}
// Best-effort teardown: append Close to whatever's still buffered and let the
// writer drain + flush it before we join the task, so the runtime isn't torn down
// mid-send. Serialization happens in the writer task now, so Drop can't panic on it.
self.batch.push(RemoteMessage::Close(self.session_id));
let batch = self.batch.take();
let writer = self
.writer
.as_mut()
.expect("writer present (checked above)");
writer.shutdown(&self.executor, Some(batch));
}
}
View on GitHub (pinned to d16f7ba2ed)
Solutions
- Do not modify the Drop guard ordering; keep the `is_none()` early-return immediately before the expect.
- If you maintain a fork, diff your Drop impl against upstream burn-remote service.rs.
- If you genuinely hit this on stock code, file a bug with the burn version and a reproduction.
Example fix
// before (fork that removed the guard)
fn drop(&mut self) {
let writer = self.writer.as_mut().expect("writer present (checked above)");
// after: restore the guard
fn drop(&mut self) {
if self.writer.is_none() { return; }
let writer = self.writer.as_mut().expect("writer present (checked above)"); Defensive patterns
Strategy: type-guard
Validate before calling
null
Type guard
// Mirrors the drop guard; use before teardown in forked code:
fn writer_ready(service: &RemoteService) -> bool { service.is_connected() } // writer.is_some() Try / catch
// Drop impls must not panic; if you fork, guard explicitly:
if let Some(writer) = self.writer.as_mut() { writer.shutdown(&self.executor, Some(batch)); } Prevention
- Never reorder the is_none() guard and expect inside Drop.
- Prefer `if let Some(writer) = ...` over expect in teardown code you own.
- Keep Drop logic free of side effects that could reset service state.
- Test drop-during-operation paths in CI when forking burn-remote.
When it happens
Trigger: Unreachable in stock code; possible only if a fork removes/reorders the `if self.writer.is_none() { return; }` guard, or if aliasing mutation sets writer to None between the check and the expect (would require unsafe/interior mutability misuse).
Common situations: Maintainers or fork authors modifying the Drop implementation; custom writer types with Drop impls that reset service state during teardown.
Related errors
- writer is set by ensure_connected
- Autodiff should not wrap an autodiff tensor.
- an autodiff float primitive must have an enabled autodiff co
- an enabled float tensor must use an autodiff primitive
- Can serialize RemoteMessage::Init
AI-assisted analysis of tracel-ai/burn@d16f7ba2ed (2026-09-05).
Data as JSON: /api/errors/d96095b61b9dc15e.
Report an issue: GitHub.