{"record":{"id":"2f2373f41d78398f","repo":"cube-js/cube","slug":"is-not-a-directory","errorCode":null,"errorMessage":"{} is not a directory","messagePattern":"(.+?) is not a directory","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"rust/cube-cli/src/commands/deploy.rs","lineNumber":76,"sourceCode":"            out.push((rel, path));\n        }\n    }\n    Ok(())\n}\n\nfn sha1_hex(data: &[u8]) -> String {\n    let mut hasher = Sha1::new();\n    hasher.update(data);\n    format!(\"{:x}\", hasher.finalize())\n}\n\npub async fn command(args: Args, ctx: &Ctx) -> Result<()> {\n    let api = ctx.api()?;\n    let deployment = args.deployment;\n    let base = format!(\"/build/api/v1/deployments/{deployment}/data-model\");\n\n    if !args.directory.is_dir() {\n        bail!(\"{} is not a directory\", args.directory.display());\n    }\n    let mut files = Vec::new();\n    collect_files(&args.directory, &args.directory, &mut files)?;\n    if files.is_empty() {\n        bail!(\"no deployable files found in {}\", args.directory.display());\n    }\n    files.sort();\n\n    // Hash local files and diff against the server's content hashes.\n    let mut query = Vec::new();\n    util::push(&mut query, \"branchName\", &args.branch);\n    let upstream = api.get(&format!(\"{base}/file-hashes\"), &query).await?;\n    let upstream = upstream.get(\"files\").cloned().unwrap_or(upstream);\n\n    let mut manifest = serde_json::Map::new();\n    let mut to_upload = Vec::new();\n    for (rel, path) in &files {\n        let data =","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/rust/cube-cli/src/commands/deploy.rs#L58-L94","documentation":"Raised by `cube deploy` (data-model deploy command) before any network work: the --directory argument supplied does not exist on disk or exists but is not a directory. The CLI validates args.directory.is_dir() up front and refuses to proceed, so a mistyped path fails fast instead of producing an empty upload.","triggerScenarios":"`cube deploy <deployment> --directory <path>` where the path does not exist, is a regular file (e.g. someone passed a schema file instead of the folder), or is a symlink to a removed target.","commonSituations":"Typo in the schema directory path; running the CLI from a different working directory in CI so a relative path no longer resolves; passing the repository root file path instead of the data-model directory; deleted checkout directory.","solutions":["Check the path exists with `ls <path>` and correct the --directory value.","Run from the directory where the relative path resolves, or pass an absolute path.","If you pointed at a file, pass the containing data-model/schema directory instead.","In CI, ensure the checkout step creates the expected directory before deploying."],"exampleFix":"// before\nrun: cube deploy 42 --directory ./schema   # dir is actually ./data-model\n// after\nrun: cube deploy 42 --directory ./data-model","handlingStrategy":"validation","validationCode":"let dir = std::path::Path::new(&args.directory);\nif !dir.is_dir() {\n    anyhow::bail!(\"--directory must be an existing directory, got: {}\", args.directory.display());\n}","typeGuard":null,"tryCatchPattern":"match result {\n    Err(e) if e.to_string().ends_with(\"is not a directory\") => {\n        // print usage hint with the expected schema directory path\n    }\n    other => other?,\n}","preventionTips":["Use absolute paths in CI; resolve relative paths against a known workdir.","Sanity-check the path with `test -d \"$DIR\"` before invoking the CLI.","Pass the data-model/schema directory, not a single file or the repo root.","Ensure CI checkout completes before the deploy step runs."],"tags":["cli","validation","filesystem","bad-argument"],"backgroundTag":"invalid-path-input","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}