{"record":{"id":"c5bd38fda5ea2d50","repo":"risingwavelabs/risingwave","slug":"root-directory-does-not-exist-c5bd38","errorCode":null,"errorMessage":"Root directory does not exist: {}","messagePattern":"Root directory does not exist: (.+?)","errorType":"exception","errorClass":"StreamExecutorError","httpStatus":null,"severity":"error","filePath":"src/stream/src/executor/source/batch_source/batch_posix_fs_list.rs","lineNumber":97,"sourceCode":"            stream_source_core,\n            metrics,\n            barrier_receiver: Some(barrier_receiver),\n            system_params,\n            rate_limit_rps,\n            barrier_manager,\n            associated_table_id: associated_table_id.unwrap(),\n        }\n    }\n\n    /// List all files from root directory and convert them to a stream of chunks\n    async fn list_files_to_stream(\n        root: String,\n        pattern: Option<String>,\n    ) -> StreamExecutorResult<impl Iterator<Item = StreamExecutorResult<StreamChunk>>> {\n        // List all files from the root directory\n        let root_path = Path::new(&root);\n        if !root_path.exists() {\n            return Err(anyhow!(\"Root directory does not exist: {}\", root).into());\n        }\n\n        // Convert pattern string to glob::Pattern if provided\n        let glob_pattern = pattern\n            .as_ref()\n            .map(|p| GlobPattern::new(p))\n            .transpose()\n            .with_context(|| format!(\"Invalid match_pattern: {:?}\", pattern))?;\n\n        let mut files = Vec::new();\n        Self::collect_files_recursive(root_path, root_path, &glob_pattern, &mut files).await?;\n\n        tracing::debug!(\n            \"BatchPosixFsListExecutor listed {} files from {}: {:?}\",\n            files.len(),\n            root,\n            files\n        );","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/risingwavelabs/risingwave/blob/6469eb736d691e8e9b8a419a57edd6429ca77417/src/stream/src/executor/source/batch_source/batch_posix_fs_list.rs#L79-L115","documentation":"The POSIX filesystem batch list source validates that the configured root directory exists on the filesystem before enumerating files. If Path::exists() is false — directory missing, deleted, unmounted, or a typo in configuration — it returns this error naming the root path, aborting the batch scan before any glob matching happens.","triggerScenarios":"list_files_to_stream is called with a root: String whose Path::new(&root).exists() is false: the directory does not exist at scan time on the node running the executor.","commonSituations":"Typo in the CONNECTOR path, directory deleted or renamed between source creation and scan, running in a container where the host path isn't mounted, permission or mount failure making the path invisible.","solutions":["Verify the path exists on the compute node: check for container/host path mismatches and mount the directory into the pod/container if needed","Correct typos in the source/root configuration and re-run","Restore or recreate the missing directory, or point the source at an existing path","Check filesystem mounts and permissions (NFS/EBS/local) if the path exists elsewhere but not on the node"],"exampleFix":"// before\nCREATE SOURCE ... WITH (connector = 'posix_fs', root = '/data/exports')  -- path missing on node\n// after\nCREATE SOURCE ... WITH (connector = 'posix_fs', root = '/mnt/data/exports')  -- verified path, mounted on node","handlingStrategy":"validation","validationCode":"use std::path::Path;\nfn root_dir_exists(root: &str) -> bool {\n    Path::new(root).is_dir()\n}\n// call before creating the source / running the scan:\nassert!(root_dir_exists(\"/mnt/data/exports\"), \"root directory missing\");","typeGuard":"fn is_existing_dir(p: &str) -> bool {\n    std::path::Path::new(p).is_dir()\n}","tryCatchPattern":"match list_files_to_stream(root, pattern) {\n    Err(e) if e.to_string().starts_with(\"Root directory does not exist\") => {\n        eprintln!(\"check the source 'root' path and node mounts: {e}\");\n    }\n    other => other?,\n}","preventionTips":["Stat the root directory on the compute node before creating the source","Use absolute, container-visible paths and verify mounts","Re-check path existence after renames/deletes upstream","Prefer connector backends (S3/Iceberg) over local FS paths when running multi-node"],"tags":["filesystem","validation","batch-source","path"],"backgroundTag":"directory-not-found","analyzedSha":"6469eb736d691e8e9b8a419a57edd6429ca77417","analyzedAt":"2026-09-11T21:06:21.487Z","contentChangedAt":"2026-09-11T21:06:21.487Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}