Report #8907
[bug\_fix] future cannot be sent between threads safely \(async Send bound\)
The root cause is that \`tokio::spawn\` \(and multi-threaded executors\) requires futures to be \`Send\` because they may be moved between OS threads by the work-stealing scheduler. Holding a type that is \`\!Send\` \(like \`Rc\`, \`RefCell\`, or a raw pointer\) across an \`.await\` point causes the future to become \`\!Send\`. The fix is to replace non-thread-safe types with their thread-safe counterparts: change \`Rc\` to \`Arc\` \(atomic reference counting\) and \`RefCell\` to \`Mutex\` or \`RwLock\` \(synchronized interior mutability\). If the state is truly thread-local and must use \`Rc\`, use \`tokio::task::LocalSet\` to spawn \`\!Send\` futures instead of \`tokio::spawn\`.
Journey Context:
A developer builds a web crawler using Tokio. They store shared state in \`Rc>\` because they are familiar with single-threaded reference counting. They spawn crawler tasks using \`tokio::spawn\(async move \{ state.borrow\_mut\(\).count \+= 1; crawl\(\).await \}\)\`. The compiler errors with 'future cannot be sent between threads safely' and points to \`Rc>\` as not implementing \`Send\`. The developer is confused: they didn't write \`unsafe\` code, why is the compiler complaining about thread safety? They search 'rust async future not send rc'. They learn that \`tokio::spawn\` moves tasks between threads dynamically for load balancing, requiring all data in the future to be \`Send\`. They realize \`Rc\` is not thread-safe \(non-atomic ops\) and \`RefCell\` is not \`Sync\`. They refactor to \`Arc>\` \(or \`std::sync::Mutex\`\). After replacing \`Rc\` with \`Arc\` and \`borrow\_mut\(\)\` with \`.lock\(\).await\`, the code compiles and runs correctly across multiple threads.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T06:46:15.091632+00:00— report_created — created