{"record":{"id":"3f5d20a32afa31cc","repo":"tracel-ai/burn","slug":"writer-is-set-by-ensure-connected","errorCode":null,"errorMessage":"writer is set by ensure_connected","messagePattern":"writer is set by ensure_connected","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/burn-remote/src/client/service.rs","lineNumber":658,"sourceCode":"        let _ = self.settings.set(connected.settings);\n        let _ = self.device_count.set(connected.device_count);\n        self.writer = Some(connected.writer);\n    }\n\n    /// Hand whatever's currently buffered to the writer task as one batch (the writer\n    /// serializes it off the runner thread). No-op when the buffer is empty; otherwise opens\n    /// the connection first if it isn't already up.\n    pub fn flush(&mut self) {\n        if self.batch.is_empty() {\n            return;\n        }\n        self.ensure_connected();\n        log::trace!(\"Flush session: {}\", self.session_id);\n        let batch = self.batch.take();\n        let writer = self\n            .writer\n            .as_ref()\n            .expect(\"writer is set by ensure_connected\");\n        writer.send(&self.executor, batch);\n    }\n}\n\nimpl Drop for RemoteService {\n    fn drop(&mut self) {\n        if self.closed {\n            return;\n        }\n        self.closed = true;\n\n        // If we never connected, there's no server-side session to close and no writer to\n        // drain — whatever was buffered never had a connection to go out on, so just drop it.\n        if self.writer.is_none() {\n            return;\n        }\n\n        // Best-effort teardown: append Close to whatever's still buffered and let the","sourceCodeStart":640,"sourceCodeEnd":676,"githubUrl":"https://github.com/tracel-ai/burn/blob/d16f7ba2ed0d41408189384044cc886fb4c8f957/crates/burn-remote/src/client/service.rs#L640-L676","documentation":"`RemoteService::flush` guarantees `self.writer` is `Some` by calling `ensure_connected()` immediately before; this expect asserts that invariant. Failing here means an internal invariant broke — connection establishment reported success (or panicked silently) without installing a writer — and is not an expected user-facing failure path.","triggerScenarios":"Only reachable if `ensure_connected` fails to actually set `self.writer` (e.g. a bug in ensure_connected on wasm paths where connect is deferred, or a fork modified the connect logic); in a stock build it should be unreachable.","commonSituations":"Running a patched fork of burn-remote where ensure_connected was changed; wasm usage where the async connect (`RemoteDevice::connect_async`) was skipped or its result not installed via `wasm_install`; race conditions from custom concurrent callers of flush.","solutions":["On wasm, make sure you awaited `RemoteDevice::connect_async(...)` before issuing tensor operations so the session is installed.","Use an unmodified release of burn/burn-remote; if you forked, re-check that ensure_connected always sets `self.writer` before returning.","Update to the latest burn version — if this reproduces on stock code it is a bug worth reporting with a minimal reproduction.","Audit for concurrent access to the same RemoteService/RemoteDevice from multiple threads without synchronization."],"exampleFix":"// before (wasm): operating before connection installed\nlet device = RemoteDevice::new(&endpoint);\nlet tensor = Tensor::<Remote<Wgsl>, 1>::from_data(...); // flush -> panic\n// after\nlet device = RemoteDevice::connect_async(&endpoint).await; // installs writer\nlet tensor = Tensor::<Remote<Wgsl>, 1>::from_data(...);","handlingStrategy":"try-catch","validationCode":"// On wasm, ensure the connection exists before any tensor op triggers flush:\n// (pseudo-check available to callers)\nasync fn ensure_ready(device: &RemoteDevice) {\n    // connect_async installs the writer; without it, ops on wasm fail\n    let _ = RemoteDevice::connect_async(device.endpoint()).await;\n}","typeGuard":null,"tryCatchPattern":"// Wrap session start so the invariant panic is caught and reported:\nlet svc = std::panic::catch_unwind(|| service.flush());\nif svc.is_err() {\n    eprintln!(\"flush before connection installed; call connect first / update burn\");\n}","preventionTips":["On wasm always await `RemoteDevice::connect_async` before tensor operations.","Use stock burn releases; re-check ensure_connected if you fork.","Avoid sharing one RemoteService across threads without a mutex.","Upgrade burn if you can reproduce this on unmodified code (it is a bug).","Add a panic hook in the client to surface the message to your telemetry."],"tags":["panic","invariant-violation","burn-remote","wasm"],"backgroundTag":"invariant-violation-panic","analyzedSha":"d16f7ba2ed0d41408189384044cc886fb4c8f957","analyzedAt":"2026-09-05T13:19:14.260Z","contentChangedAt":"2026-09-05T13:19:14.260Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}