zeroclaw-labs/zeroclaw · error · anyhow::Error
Lark/Feishu marker target is not a file
Error message
Lark/Feishu marker target is not a file
What it means
resolve_lark_media_marker stats the validated path and requires metadata.is_file() — the marker target must resolve to a regular file, not a directory, fifo, socket or device. All scheme/workspace containment checks already passed by this point, so this error specifically means: the path exists, is inside the workspace, but is not something uploadable as image/file content.
Source
Thrown at crates/zeroclaw-channels/src/lark.rs:656
);
anyhow::bail!("Lark/Feishu marker target resolves outside workspace_dir");
}
Ok(candidate)
}
fn resolve_lark_media_marker(
marker: &LarkOutgoingMediaMarker,
workspace_dir: Option<&Path>,
) -> anyhow::Result<LarkResolvedMediaMarker> {
let path = validate_lark_marker_target(&marker.target, workspace_dir)?;
let metadata = std::fs::metadata(&path).map_err(|err| {
anyhow::Error::msg(format!(
"read Lark/Feishu marker target metadata failed: {err}"
))
})?;
if !metadata.is_file() {
anyhow::bail!("Lark/Feishu marker target is not a file");
}
if metadata.len() == 0 {
anyhow::bail!("Lark/Feishu marker target is empty");
}
let file_name = path
.file_name()
.and_then(|name| name.to_str())
.unwrap_or("attachment")
.to_string();
Ok(LarkResolvedMediaMarker {
kind: marker.kind,
path,
file_name,
})
}
async fn build_lark_image_upload_form(marker: &LarkResolvedMediaMarker) -> anyhow::Result<Form> {View on GitHub (pinned to 88bb9c8533)
Solutions
- Point the marker at the concrete file including its filename ("screenshots/run-42.png", not "screenshots/")
- Have the file-producing tool return the exact artifact path it wrote and feed that verbatim into the marker
- If attaching multiple files, emit one marker per file rather than one marker per directory
Example fix
// before
{ "kind": "image", "target": "reports/daily" } // a directory
// after
{ "kind": "image", "target": "reports/daily/chart.png" } Defensive patterns
Strategy: validation
Validate before calling
// Before sending, confirm the marker resolves to a regular file:
let p = std::fs::canonicalize(workspace.join(target.trim()))?;
anyhow::ensure!(std::fs::metadata(&p)?.is_file(), "marker target is not a regular file: {p:?}"); Try / catch
if let Err(e) = channel.send(&msg).await {
if e.to_string().contains("is not a file") {
// append the concrete filename to the target and retry
}
} Prevention
- Always emit file paths with the filename component — never a bare directory
- Return exact artifact paths from tools and pass them through unmodified
When it happens
Trigger: A marker points at a directory ("screenshots/" or "attachments" without a filename) or at a special file; std::fs::metadata succeeds, is_file() is false, and send/finalize_draft bail before reading bytes or building the upload form.
Common situations: Agent truncates a path to its folder; tool writes to a directory and passes the folder as the artifact; marker built by joining a base dir while the filename component was empty.
Related errors
- Lark/Feishu marker target is empty
- Lark/Feishu marker target uses a disallowed scheme
- Lark/Feishu marker target resolves outside workspace_dir
- git channel: reading private_key_path `{path}` failed: {e}
- send failed {context}: status={status}, body={body}
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/4f51c8cd0575b0a8.
Report an issue: GitHub.