{"record":{"id":"d681bd3d5419aee4","repo":"astrid-runtime/astrid","slug":"mcp-attach-workspace-must-be-absolute-value","errorCode":null,"errorMessage":"MCP attach workspace must be absolute: {value}","messagePattern":"MCP attach workspace must be absolute: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/mcp/gateway.rs","lineNumber":976,"sourceCode":"fn mint_hook_token() -> String {\n    format!(\n        \"{}{}\",\n        Uuid::new_v4().as_simple(),\n        Uuid::new_v4().as_simple()\n    )\n}\n\nfn mint_boot_token() -> String {\n    Uuid::new_v4().as_simple().to_string()\n}\n\nfn validate_workspace(value: &str) -> Result<PathBuf> {\n    if value.is_empty() {\n        anyhow::bail!(\"MCP attach workspace is empty\");\n    }\n    let path = PathBuf::from(value);\n    if !path.is_absolute() {\n        anyhow::bail!(\"MCP attach workspace must be absolute: {value}\");\n    }\n    std::fs::canonicalize(&path)\n        .with_context(|| format!(\"failed to resolve MCP attach workspace {value}\"))\n}\n\nfn set_socket_mode(path: &Path) -> Result<()> {\n    #[cfg(unix)]\n    {\n        use std::os::unix::fs::PermissionsExt;\n        std::fs::set_permissions(path, std::fs::Permissions::from_mode(0o600))?;\n    }\n    Ok(())\n}\n\n#[cfg(test)]\n#[path = \"gateway_tests.rs\"]\nmod tests;\n","sourceCodeStart":958,"sourceCodeEnd":994,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/mcp/gateway.rs#L958-L994","documentation":"validate_workspace requires the workspace path to be absolute because the gateway may resolve it independently of the client's working directory. Relative paths are ambiguous across the client/gateway process boundary, so they are rejected with the offending value in the message. After the absolute check, the path is canonicalized to its real location.","triggerScenarios":"Attach registration workspace_abs is a relative path like \"myproject\" or \".\"; workspace built by joining without a base; tilde paths like \"~/proj\" that were never expanded.","commonSituations":"Client run from a different cwd than the gateway; shell tilde not expanded in config; user entered a project name instead of a full path in settings.","solutions":["Convert the workspace to an absolute path (fs::canonicalize or cwd.join) before sending the registration","Expand ~/ in config before storing it (e.g. with the dirs/home_dir crates)","Use the absolute path returned by a prior canonicalize when building the registration","Ensure the directory exists so canonicalize also succeeds"],"exampleFix":"// before\nworkspace_abs: \"~/projects/app\".into(),\n// after\nlet base = dirs::home_dir().context(\"no home dir\")?;\nworkspace_abs: base.join(\"projects/app\").canonicalize()?.display().to_string(),","handlingStrategy":"validation","validationCode":"let p = PathBuf::from(&reg.workspace_abs);\nif !p.is_absolute() { return Err(format!(\"workspace must be absolute, got {}\", reg.workspace_abs)); }\nlet canonical = std::fs::canonicalize(&p)?;","typeGuard":"fn is_absolute_workspace(p: &str) -> bool { PathBuf::from(p).is_absolute() }","tryCatchPattern":null,"preventionTips":["Canonicalize the workspace before storing it in any registration","Expand ~ explicitly in config loading","Avoid passing relative paths across process boundaries"],"tags":["validation","mcp","filesystem"],"backgroundTag":"invalid-argument-value","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}