{"record":{"id":"2c86b4526cf96d17","repo":"flxzt/rnote","slug":"channel-closed-before-receiving-a-response-from-lo","errorCode":null,"errorMessage":"Channel closed before receiving a response from loader thread.","messagePattern":"Channel closed before receiving a response from loader thread\\.","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/rnote-ui/src/dialogs/import.rs","lineNumber":556,"sourceCode":"                            && let Err(e) = tx_import.unbounded_send(Err(e))\n                        {\n                            error!(\n                                \"Failed to load PDF, but failed to send signal through channel. Err: {e:?}\"\n                            );\n                            return;\n                        };\n\n                        if let Err(e) = tx_import.unbounded_send(Ok(true)) {\n                            error!(\n                                \"PDF file imported, but failed to send signal through channel. Err: {e:?}\"\n                            );\n                        }\n                    }\n                ));\n\n                match rx_import.next().await {\n                    Some(res) => res,\n                    None => Err(anyhow::anyhow!(\n                        \"Channel closed before receiving a response from loader thread.\"\n                    )),\n                }\n            } else {\n                Ok(false)\n            }\n        }\n        None => Err(anyhow::anyhow!(\n            \"Channel closed before receiving a response from dialog.\"\n        )),\n    }\n}\n\n/// Imports the file as Xopp with an import dialog.\n///\n/// Returns true when the file was imported, else false.\npub(crate) async fn dialog_import_xopp_w_prefs(\n    appwindow: &RnAppWindow,","sourceCodeStart":538,"sourceCodeEnd":574,"githubUrl":"https://github.com/flxzt/rnote/blob/bbc5354502ba2fc83eec2670b535348825e679a6/crates/rnote-ui/src/dialogs/import.rs#L538-L574","documentation":"Thrown when the async channel (`rx_import`) used to receive the import result from the spawned PDF loader thread is dropped/closed before sending a value, so `rx_import.next().await` yields None. Indicates the loader task panicked, was cancelled, or the sender was dropped without emitting a result.","triggerScenarios":"In `dialog_import_pdf_w_prefs`, the spawned loader thread/task ends without sending on `tx_import` (panic inside PDF parsing, early return, or sender dropped), leaving `rx_import.next()` to return None.","commonSituations":"Loader thread panics on a malformed PDF; task aborted due to app shutdown or window close mid-import; a code change introduces a code path that drops the sender before `send`.","solutions":["Inspect the loader thread for panics/early returns — wrap the task body so a result (including error) is always sent through the channel.","Ensure `tx_import` is not dropped before the load completes (keep it alive via move into the task and send in all branches).","Retry the import; if reproducible, reproduce with the specific PDF and report/fix the parser panic.","Replace bare None handling with logging the loader-side error to diagnose which path dropped the sender."],"exampleFix":"// before\nmatch rx_import.next().await {\n    Some(res) => res,\n    None => Err(anyhow::anyhow!(\"Channel closed before receiving a response from loader thread.\")),\n}\n// after\nmatch rx_import.next().await {\n    Some(res) => res,\n    None => {\n        tracing::error!(\"PDF loader thread ended without sending a result\");\n        Err(anyhow::anyhow!(\"Channel closed before receiving a response from loader thread.\"))\n    }\n}\n// loader side: guarantee a send in every branch\ngstd::panic::catch_unwind(...); tx_import.send(result).await.ok();","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match rx_import.next().await {\n    Some(res) => res,\n    None => { tracing::error!(\"loader thread dropped sender\"); Err(anyhow!(\"loader ended without result\")) }\n}","preventionTips":["Always send a Result through the channel in every loader branch","Catch panics in the loader task and convert them to Err results","Keep the sender alive for the whole task lifetime (move into closure)"],"tags":["async","channel","pdf-import","threading"],"backgroundTag":"broken-pipe","analyzedSha":"bbc5354502ba2fc83eec2670b535348825e679a6","analyzedAt":"2026-09-08T13:20:33.747Z","contentChangedAt":"2026-09-08T13:20:33.747Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}