{"record":{"id":"fdc0f67d1a39c39f","repo":"windmill-labs/windmill","slug":"could-not-create-dir-directory-path-e","errorCode":null,"errorMessage":"could not create dir '{directory_path}': {e}","messagePattern":"could not create dir '(.+?)': (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/windmill-common/src/utils.rs","lineNumber":503,"sourceCode":"    (per_page, offset)\n}\n\npub async fn now_from_db<'c, E: sqlx::PgExecutor<'c>>(\n    db: E,\n) -> Result<chrono::DateTime<chrono::Utc>> {\n    Ok(sqlx::query_scalar!(\"SELECT now()\")\n        .fetch_one(db)\n        .warn_after_seconds_with_sql(1, \"now_from_db\".to_string())\n        .await?\n        .unwrap())\n}\n\npub async fn create_directory_async(directory_path: &str) {\n    AsyncDirBuilder::new()\n        .recursive(true)\n        .create(directory_path)\n        .await\n        .unwrap_or_else(|e| panic!(\"could not create dir '{}': {}\", directory_path, e));\n}\n\npub fn create_directory_sync(directory_path: &str) {\n    SyncDirBuilder::new()\n        .recursive(true)\n        .create(directory_path)\n        .unwrap_or_else(|e| panic!(\"could not create dir '{}': {}\", directory_path, e));\n}\n\n#[track_caller]\npub fn not_found_if_none<T, U: AsRef<str>>(opt: Option<T>, kind: &str, name: U) -> Result<T> {\n    if let Some(o) = opt {\n        Ok(o)\n    } else {\n        let loc = Location::caller();\n        Err(Error::NotFound(format!(\n            \"{} not found at name {} ({}:{})\",\n            kind,","sourceCodeStart":485,"sourceCodeEnd":521,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/windmill-common/src/utils.rs#L485-L521","documentation":"Windmill workers and servers create local directories (job working dirs, caches, logs) under WINDMILL_DIR on startup or when handling jobs. `create_directory_async` builds the directory recursively (like `mkdir -p`) and panics with this message if the OS refuses, e.g. due to permissions, a read-only filesystem, or a path component being a file. The panic kills the calling task (worker startup or job run).","triggerScenarios":"Calling `create_directory_async(dir)` where the async tokio directory builder returns an error: parent path is a file, mount point read-only, EACCES on the target path, disk full, or invalid characters in the path.","commonSituations":"WINDMILL_DIR volume mounted read-only; container running as non-root but volume owned by root; Kubernetes emptyDir/persistence misconfigured; a file exists where the directory should be; NFS/permission issues on shared storage.","solutions":["Check the inner error `{e}` in the message for the exact OS errno (permission denied, read-only fs, etc.)","Verify WINDMILL_DIR points to a writable volume and is owned by the user the worker runs as","Ensure the mount is not read-only (`mount | grep <path>` / volume ro flags in compose/k8s)","Remove any regular file that occupies a path component of the target directory","Run the container with the correct fsGroup/runAsUser so the volume is writable"],"exampleFix":"// before: worker running as user 1000 with root-owned volume\nvolumes:\n  - worker-data:/tmp/windmill\n// after: make volume writable\nvolumes:\n  - worker-data:/tmp/windmill\n# plus in k8s: securityContext.fsGroup: 1000 or chown 1000:1000 on the host dir","handlingStrategy":"validation","validationCode":"const fs = require('fs');\nfunction assertWritableDirParent(dir) {\n  let p = require('path').dirname(dir);\n  while (p !== '/' && !fs.existsSync(p)) p = require('path').dirname(p);\n  fs.accessSync(p, fs.constants.W_OK); // throws if not writable\n}\nassertWritableDirParent(process.env.WINDMILL_DIR || '/tmp/windmill');","typeGuard":null,"tryCatchPattern":"// Wrap any custom automation that creates Windmill dirs\ntry {\n  await fs.promises.mkdir(target, { recursive: true });\n} catch (e) {\n  if (e.code === 'EACCES' || e.code === 'EROFS') {\n    console.error(`Fix volume permissions/read-only mount for ${target}: ${e.message}`);\n  }\n  throw e;\n}","preventionTips":["Mount WINDMILL_DIR on a writable volume with correct ownership (match container UID/fsGroup)","Never mount the storage path read-only","Check for files colliding with expected directories after image upgrades","Verify writable path in CI smoke tests before deploy"],"tags":["rust","filesystem","permissions","worker"],"backgroundTag":"mkdir-permission-denied","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}