Report #4613
[bug\_fix] recursive async function requires boxing or future has infinite size
Use the \`async-recursion\` crate by adding \`\#\[async\_recursion\]\` to the function, or manually convert the function to return \`Pin \+ Send>>\` and wrap recursive calls in \`Box::pin\`.
Journey Context:
Developer implements an async file system walker: \`async fn traverse\(path: PathBuf\) -> Vec \{ let mut entries = vec\!\[\]; for entry in read\_dir\(path\).await.unwrap\(\) \{ if entry.file\_type\(\).await.unwrap\(\).is\_dir\(\) \{ entries.extend\(traverse\(entry.path\(\)\).await\); \} \} entries \}\`. The compiler fails with a cryptic error about 'future has infinite size' or 'type recursion limit reached'. The developer realizes that \`async fn\` returns an opaque \`impl Future\` type whose size must be known at compile time; recursion creates a type that contains itself \(the future awaits another future of the same type\), causing infinite size. They try to use \`Box::pin\` but struggle with the exact syntax, \`Pin\`, and \`Send\` bounds required for \`tokio::spawn\`. After searching, they find the \`async-recursion\` crate which handles the boxing automatically. Adding \`\#\[async\_recursion\]\` to the function works because it transforms the function to return a boxed future, storing the recursive state on the heap rather than the stack, breaking the infinite size cycle since the \`Box\` has a known size \(just a pointer\).
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-15T19:47:39.329979+00:00— report_created — created