{"record":{"id":"0ddf33b1a63897c5","repo":"BloopAI/vibe-kanban","slug":"operation-forcibly-terminated-due-to-hard-timeout","errorCode":null,"errorMessage":"Operation forcibly terminated due to hard timeout","messagePattern":"Operation forcibly terminated due to hard timeout","errorType":"exception","errorClass":"FilesystemError","httpStatus":null,"severity":"error","filePath":"crates/services/src/services/filesystem.rs","lineNumber":160,"sourceCode":"                .await\n        });\n\n        let hard_timeout = tokio::time::sleep(std::time::Duration::from_millis(hard_timeout_ms));\n        tokio::pin!(hard_timeout);\n\n        tokio::select! {\n            res = &mut scan_handle => {\n                match res {\n                    Ok(Ok(repos)) => Ok(repos),\n                    Ok(Err(err)) => Err(err),\n                    Err(join_err) => Err(FilesystemError::Io(\n                        std::io::Error::other(join_err.to_string())))\n                }\n                }\n            _ = &mut hard_timeout => {\n                scan_handle.abort();\n                tracing::warn!(\"list_git_repos_with_timeout: hard timeout reached after {}ms\", hard_timeout_ms);\n                Err(FilesystemError::Io(std::io::Error::new(\n                    std::io::ErrorKind::TimedOut,\n                    \"Operation forcibly terminated due to hard timeout\",\n                )))\n            }\n        }\n    }\n\n    #[cfg_attr(feature = \"qa-mode\", allow(unused_variables))]\n    pub async fn list_common_git_repos(\n        &self,\n        timeout_ms: u64,\n        hard_timeout_ms: u64,\n        max_depth: Option<usize>,\n    ) -> Result<Vec<DirectoryEntry>, FilesystemError> {\n        #[cfg(feature = \"qa-mode\")]\n        {\n            tracing::info!(\n                \"QA mode: returning hardcoded QA repos instead of scanning common directories\"","sourceCodeStart":142,"sourceCodeEnd":178,"githubUrl":"https://github.com/BloopAI/vibe-kanban/blob/4deb7eca8f381f7cbc1f9d15515a9ab8f8009053/crates/services/src/services/filesystem.rs#L142-L178","documentation":"list_git_repos_with_timeout scans the filesystem for git repositories under a hard deadline. If the scan doesn't finish within hard_timeout_ms, the scan task is aborted and this TimedOut error is returned to prevent the API call from hanging on huge or slow filesystems.","triggerScenarios":"Calling list_git_repos or list_common_git_repos against a directory tree so large/slow (many directories, network mounts, spinning disk) that scanning exceeds the hard timeout.","commonSituations":"Pointing the directory scan at a home directory or NFS/SMB mount with thousands of directories; antivirus or FUSE filesystem slowdown; a path containing a huge node_modules/build tree; I/O contention from concurrent scans.","solutions":["Scan a narrower root directory that excludes huge subtrees (build artifacts, node_modules).","Increase the hard timeout configuration if your filesystem is legitimately slow (network mounts).","Avoid scanning network-mounted paths; copy projects to local disk or mount without FUSE overhead.","Retry later if transient I/O load caused the timeout; check the tracing warn log for the measured duration."],"exampleFix":"// before\nfilesystem.list_git_repos(Path::new(\"/home/user\"), None).await?;\n// after\nfilesystem.list_git_repos(Path::new(\"/home/user/projects\"), Some(hard_timeout_ms * 4)).await?;","handlingStrategy":"fallback","validationCode":"// pre-check: avoid scanning obviously huge trees\nlet entries = fs::read_dir(root)?.count();\nif entries > 50_000 {\n    anyhow::bail!(\"root {} too large to scan\", root.display());\n}","typeGuard":null,"tryCatchPattern":"match list_git_repos(root).await {\n    Err(FilesystemError::Io(e)) if e.kind() == ErrorKind::TimedOut\n        && e.to_string().contains(\"hard timeout\") => {\n        // fall back to cached index or prompt user for a narrower directory\n    }\n    other => other,\n}","preventionTips":["Point repo scans at dedicated project directories, not home or network mounts.","Raise the hard timeout for known-slow (NFS/FUSE) filesystems.","Cache scan results and invalidate on directory-change events instead of rescanning."],"tags":["filesystem","timeout","scan"],"backgroundTag":"operation-hard-timeout","analyzedSha":"4deb7eca8f381f7cbc1f9d15515a9ab8f8009053","analyzedAt":"2026-08-29T09:24:13.446Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}