zeroclaw-labs/zeroclaw · error · anyhow::Error
Lark/Feishu marker target is empty
Error message
Lark/Feishu marker target is empty
What it means
validate_lark_marker_target is the first stop when turning an outgoing media marker (image/file kind like image, document, video, voice) into an uploadable local path; it rejects a target that trims to empty before any scheme or workspace checks. The marker target is supposed to be a workspace-relative (or absolute) file path, so an empty string means the agent/tool that produced the marker emitted no path at all.
Source
Thrown at crates/zeroclaw-channels/src/lark.rs:575
}
fn lark_outgoing_media_from_marker(
kind: String,
target: String,
) -> Option<LarkOutgoingMediaMarker> {
Some(LarkOutgoingMediaMarker {
kind: LarkOutgoingMediaKind::from_marker_kind(&kind)?,
target,
})
}
fn validate_lark_marker_target(
target: &str,
workspace_dir: Option<&Path>,
) -> anyhow::Result<PathBuf> {
let trimmed = target.trim();
if trimmed.is_empty() {
anyhow::bail!("Lark/Feishu marker target is empty");
}
let lower = trimmed.to_ascii_lowercase();
if lower.starts_with("http://")
|| lower.starts_with("https://")
|| lower.starts_with("data:")
|| lower.starts_with("file:")
|| lower.contains("://")
{
::zeroclaw_log::record!(
WARN,
::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Note)
.with_attrs(::serde_json::json!({"reason": "disallowed_scheme"})),
"lark: marker target uses disallowed scheme"
);
anyhow::bail!("Lark/Feishu marker target uses a disallowed scheme");
}
View on GitHub (pinned to 88bb9c8533)
Solutions
- Fix the marker producer (agent tool or prompt) so the target is always the non-empty path of the generated file
- Validate marker payloads at the boundary where the model's structured output is parsed — drop or retry markers with a blank target before they reach the channel
- If a file-generation tool failed upstream, make its failure visible instead of letting an empty marker flow into send
Defensive patterns
Strategy: validation
Validate before calling
// Validate markers at parse time, before they reach the channel:
fn valid_marker(kind: &str, target: &str) -> bool {
matches!(kind.to_ascii_lowercase().as_str(), "image"|"photo"|"document"|"file"|"video"|"audio"|"voice")
&& !target.trim().is_empty()
} Try / catch
if let Err(e) = channel.send(&msg).await {
if e.to_string().contains("marker target is empty") {
// drop or regenerate the marker upstream; do not retry the same message
}
} Prevention
- Validate structured agent output (marker kind + target) at the parse boundary
- Make file-producing tools return the written path and inject it into markers, instead of letting the model type one
When it happens
Trigger: The model emits a media marker (e.g. an image attachment directive) whose target field is "" or only whitespace; resolve_lark_media_marker (called from send/finalize_draft) routes it into validate_lark_marker_target and the empty-trim guard fires.
Common situations: Agent prompt/template for Lark media output has an empty placeholder; a tool that generates files failed but still emitted a marker; JSON marker parsing lost the path field (key typo like 'path' vs 'target').
Related errors
- Lark/Feishu marker target uses a disallowed scheme
- Lark/Feishu marker target is not a file
- Lark/Feishu marker target resolves outside workspace_dir
- modal custom_id exceeds Discord's 100-char limit; cannot ope
- slash command registration failed for '{name}' ({status}): {
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/89dd40c418981282.
Report an issue: GitHub.