{"record":{"id":"69cd3b8e3be8ec98","repo":"sinelaw/fresh","slug":"missing-path-in-response","errorCode":null,"errorMessage":"missing path in response","messagePattern":"missing path in response","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/fresh-editor/src/services/remote/filesystem.rs","lineNumber":539,"sourceCode":"        let params = serde_json::json!({\n            \"path\": path.to_string_lossy(),\n            \"parents\": true\n        });\n        self.channel\n            .request_blocking(\"mkdir\", params)\n            .map_err(Self::to_io_error)?;\n        Ok(())\n    }\n\n    fn canonicalize(&self, path: &Path) -> io::Result<PathBuf> {\n        let params = serde_json::json!({\"path\": path.to_string_lossy()});\n        let result = self\n            .channel\n            .request_blocking(\"realpath\", params)\n            .map_err(Self::to_io_error)?;\n\n        let canonical = result.get(\"path\").and_then(|v| v.as_str()).ok_or_else(|| {\n            io::Error::new(io::ErrorKind::InvalidData, \"missing path in response\")\n        })?;\n\n        Ok(PathBuf::from(canonical))\n    }\n\n    fn current_uid(&self) -> u32 {\n        // We don't know the remote user's UID easily, return 0\n        // This is used for ownership checks which we skip for remote\n        0\n    }\n\n    fn remote_connection_info(&self) -> Option<&str> {\n        Some(&self.connection_string)\n    }\n\n    fn is_remote_connected(&self) -> bool {\n        self.channel.is_connected()\n    }","sourceCodeStart":521,"sourceCodeEnd":557,"githubUrl":"https://github.com/sinelaw/fresh/blob/67894ca5463dbd7a89bb31add4627c27d6b79d83/crates/fresh-editor/src/services/remote/filesystem.rs#L521-L557","documentation":"canonicalize sent a realpath request to the remote agent and the response JSON had no string under the \"path\" key. The adapter requires the canonical path field, so an absent/malformed path is raised as InvalidData instead of returning an empty PathBuf.","triggerScenarios":"A realpath response missing \"path\" — agent error payload, protocol mismatch, or the remote failing to resolve the given path while still returning a 200-style result object.","commonSituations":"Requesting canonicalize on a nonexistent remote path, agent version with renamed response fields, or a custom remote agent that returns errors in a different schema.","solutions":["Verify the remote path exists before calling canonicalize (e.g. stat/metadata first).","Check agent/editor protocol compatibility; ensure realpath replies with {\"path\": \"...\"}.","Log the raw realpath response and treat missing-path as a not-found condition for the caller."],"exampleFix":"// before\nlet canon = remote_fs.canonicalize(&path)?;\n// after\nif !remote_fs.exists(&path) {\n    eprintln!(\"skipping canonicalize for missing path {path}\");\n    return Ok(path.into());\n}\nlet canon = remote_fs.canonicalize(&path)?;","handlingStrategy":"validation","validationCode":"if !remote_fs.exists(&path) { return Err(format!(\"cannot canonicalize missing path: {}\", path.display()).into()); }","typeGuard":"fn valid_realpath_response(v: &serde_json::Value) -> bool { v.get(\"path\").and_then(|p| p.as_str()).map(|s| !s.is_empty()).unwrap_or(false) }","tryCatchPattern":"let canon = remote_fs.canonicalize(&path).unwrap_or_else(|_| path.to_path_buf());","preventionTips":["Stat the remote path before canonicalizing to ensure it exists","Fall back to the original path when realpath fails and exactness is not required","Verify agent realpath response schema {\"path\": string} when onboarding new remote types"],"tags":["remote","protocol","json","realpath"],"backgroundTag":"unexpected-response-shape","analyzedSha":"67894ca5463dbd7a89bb31add4627c27d6b79d83","analyzedAt":"2026-09-13T15:04:03.701Z","contentChangedAt":"2026-09-13T15:04:03.701Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}