{"record":{"id":"e8f1198b15916e27","repo":"FuelLabs/sway","slug":"missing-path-for-new-command","errorCode":null,"errorMessage":"missing path for new command","messagePattern":"missing path for new command","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"forc/src/cli/commands/new.rs","lineNumber":65,"sourceCode":"    let Command {\n        contract,\n        script,\n        predicate,\n        library,\n        workspace,\n        name,\n        path,\n    } = command;\n\n    match &name {\n        Some(name) => validate_project_name(name)?,\n        None => {\n            // If there is no name specified for the project, the last component of the `path` (directory name)\n            // will be used by default so we should also check that.\n            let project_path = PathBuf::from(&path);\n            let directory_name = project_path\n                .file_name()\n                .ok_or_else(|| anyhow!(\"missing path for new command\"))?\n                .to_string_lossy();\n            validate_project_name(&directory_name)?;\n        }\n    }\n\n    let dir_path = Path::new(&path);\n    if dir_path.exists() {\n        forc_result_bail!(\n            \"Directory \\\"{}\\\" already exists.\\nIf you wish to initialise a forc project inside \\\n            this directory, consider using `forc init --path {}`\",\n            dir_path.canonicalize()?.display(),\n            dir_path.display(),\n        );\n    } else {\n        std::fs::create_dir_all(dir_path)?;\n    }\n\n    let init_cmd = InitCommand {","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/FuelLabs/sway/blob/47e5e902faa42baf652dd6a0c88cd23390c1a614/forc/src/cli/commands/new.rs#L47-L83","documentation":"forc new falls back to the final path component as the project name when --name is absent; Path::file_name() returns None for paths with no final component — a path ending in '..' or a root like '/' — and this ok_or_else converts that into \"missing path for new command\" before validate_project_name ever runs.","triggerScenarios":"`forc new --path ..`, `forc new --path .` is fine ('.' has file_name \".\"), but `--path ..` or `--path /` yields None. Concretely any path whose last component normalizes to a parent reference or the filesystem root.","commonSituations":"Shell scripts computing a destination path that collapses to '..' (e.g. joining an empty variable), or invoking forc new at the filesystem root / with a trailing '..' in CI.","solutions":["Pass an explicit project name: `forc new --name myproj --path <dir>`","Give a path whose last component is a real directory name (no trailing '..' or '/')","Sanitize script variables so empty strings don't turn the path into '..'"],"exampleFix":"# before\nforc new --path ..\n\n# after\nforc new --name my_project --path ../my_project","handlingStrategy":"validation","validationCode":"// Mirror forc's own logic: without --name the last path component becomes the project name.\nlet name = match (&command.name, std::path::Path::new(&command.path).file_name()) {\n    (Some(n), _) => n.clone(),\n    (None, Some(last)) => last.to_string_lossy().into_owned(),\n    (None, None) => anyhow::bail!(\"--path must end in a directory name, or pass --name\"),\n};","typeGuard":"fn path_has_file_name(p: &str) -> bool {\n    std::path::Path::new(p).file_name().is_some()\n}","tryCatchPattern":null,"preventionTips":["Always pass --name in scripts that compute destination paths from variables","Reject paths ending in '..', '/', or drive roots before shelling out to forc new"],"tags":["forc","new","path","cli-args"],"backgroundTag":null,"analyzedSha":"47e5e902faa42baf652dd6a0c88cd23390c1a614","analyzedAt":"2026-08-16T07:57:45.555Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}