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

  1. Do not modify the Drop guard ordering; keep the `is_none()` early-return immediately before the expect.
  2. If you maintain a fork, diff your Drop impl against upstream burn-remote service.rs.
  3. 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

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


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