{"record":{"id":"90324b689b1b2c74","repo":"rustdesk/rustdesk","slug":"failed-to-empty-clipboard-files-for-conn-id","errorCode":null,"errorMessage":"Failed to empty clipboard files for conn_id {}","messagePattern":"Failed to empty clipboard files for conn_id (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/clipboard.rs","lineNumber":212,"sourceCode":"            }\n        }\n    }\n    #[allow(unused_mut)]\n    if let Some(mut ctx) = ctx.as_mut() {\n        #[cfg(target_os = \"linux\")]\n        {\n            use clipboard::platform::unix;\n            if unix::fuse::empty_local_files(_side == ClipboardSide::Client, _conn_id) {\n                ctx.try_empty_clipboard_files(_side);\n            }\n        }\n        #[cfg(target_os = \"macos\")]\n        {\n            ctx.try_empty_clipboard_files(_side);\n            // No need to make sure the context is enabled.\n            clipboard::ContextSend::proc(|context| -> ResultType<()> {\n                if !context.empty_clipboard(_conn_id)? {\n                    bail!(\"Failed to empty clipboard files for conn_id {}\", _conn_id);\n                }\n                Ok(())\n            })?;\n        }\n    }\n    Ok(())\n}\n\n#[cfg(target_os = \"windows\")]\npub fn try_empty_clipboard_files(side: ClipboardSide, conn_id: i32) {\n    log::debug!(\"try to empty {} cliprdr for conn_id {}\", side, conn_id);\n    let _ = clipboard::ContextSend::proc(|context| -> ResultType<()> {\n        context.empty_clipboard(conn_id)?;\n        Ok(())\n    });\n}\n\n#[cfg(target_os = \"windows\")]","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/rustdesk/rustdesk/blob/91c9fccbb0f7bfe5f11644d5fbdec9b23fa10540/src/clipboard.rs#L194-L230","documentation":"After asking the server-side file clipboard context to empty the files for a connection, it reports empty_clipboard(conn_id) == false, meaning the per-connection file clipboard data could not be cleared for that conn_id. The library bails so the caller knows cleanup did not take effect.","triggerScenarios":"try_empty_clipboard_files for a _conn_id whose file clipboard entry no longer exists or was already cleared — ContextSend::proc finds a live context but empty_clipboard returns false for the given connection id (double cleanup, unknown conn_id, or state mismatch).","commonSituations":"Calling empty twice for the same connection (both disconnect paths racing); conn_id already invalid because the peer disconnected concurrently; macOS server-side file clipboard state removed by another path before this call.","solutions":["Guard against duplicate cleanup — skip if the connection was already marked cleaned.","Treat a false return during disconnect as non-fatal: log a warning instead of propagating the error.","Verify conn_id passed in matches the active connection (no stale id from a closed session)."],"exampleFix":"// before\n try_empty_clipboard_files(conn_id, side)?;\n// after: cleanup is best-effort\n if let Err(e) = try_empty_clipboard_files(conn_id, side) {\n     log::warn!(\"empty clipboard files: {:?}\", e);\n }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"if let Err(e) = try_empty_clipboard_files(conn_id, side) {\n    log::warn!(\"empty clipboard files for conn {}: {}\", conn_id, e);\n}","preventionTips":["Track which connections have already been cleaned to avoid double-empty","Validate conn_id is still active before cleanup","Treat teardown-time clipboard errors as warnings, not failures"],"tags":["clipboard","file-transfer","cleanup"],"backgroundTag":"clipboard-clear-failed","analyzedSha":"91c9fccbb0f7bfe5f11644d5fbdec9b23fa10540","analyzedAt":"2026-09-10T19:53:44.083Z","contentChangedAt":"2026-09-10T19:53:44.083Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}