{"record":{"id":"c60f77239caf5985","repo":"zeroclaw-labs/zeroclaw","slug":"whatsapp-marker-target-is-empty","errorCode":null,"errorMessage":"WhatsApp marker target {} is empty","messagePattern":"WhatsApp marker target (.+?) is empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/zeroclaw-channels/src/whatsapp_web.rs","lineNumber":1796,"sourceCode":"                \"TTS: sent voice note ({} bytes, ~{}s)\",\n                audio_len, estimated_seconds\n            )\n        );\n        Ok(())\n    }\n\n    #[cfg(feature = \"whatsapp-web\")]\n    async fn send_media_marker(\n        client: &whatsapp_rust::Client,\n        to: &wacore_binary::jid::Jid,\n        marker: &WhatsAppMediaMarker,\n        path: &Path,\n    ) -> Result<()> {\n        let bytes = tokio::fs::read(path)\n            .await\n            .with_context(|| format!(\"read WhatsApp marker target {}\", path.display()))?;\n        if bytes.is_empty() {\n            anyhow::bail!(\"WhatsApp marker target {} is empty\", path.display());\n        }\n\n        let media_type = marker.kind.media_type();\n        let mime = marker.kind.mime_for_path(path);\n\n        use whatsapp_rust::upload::UploadOptions;\n        let upload = client\n            .upload(bytes, media_type, UploadOptions::default())\n            .await\n            .map_err(|e| anyhow::Error::msg(format!(\"WhatsApp media upload failed: {e}\")))?;\n\n        let media_key = upload.media_key_vec();\n        let file_enc_sha256 = upload.file_enc_sha256_vec();\n        let file_sha256 = upload.file_sha256_vec();\n        let outgoing = match marker.kind {\n            WhatsAppMediaKind::Image => waproto::whatsapp::Message {\n                image_message: Some(Box::new(waproto::whatsapp::message::ImageMessage {\n                    url: Some(upload.url),","sourceCodeStart":1778,"sourceCodeEnd":1814,"githubUrl":"https://github.com/zeroclaw-labs/zeroclaw/blob/88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc/crates/zeroclaw-channels/src/whatsapp_web.rs#L1778-L1814","documentation":"When a message attachment marker points at a local file, the WhatsApp Web channel reads the file before uploading; a successful read of a zero-byte file bails with the path. This is distinct from a read failure (which surfaces the underlying IO error with context `read WhatsApp marker target ...`).","triggerScenarios":"A marker referencing an existing but empty (0-byte) file — e.g. a download that was started but aborted, a placeholder file created ahead of content, or a producer that failed silently.","commonSituations":"Racing a file producer (sending before the file was flushed); upstream tools writing empty artifacts on failure; cleanup jobs truncating files in place while sends reference them.","solutions":["Wait for the file to be non-empty before sending the marker message (poll its size or get a completion signal from the producer).","Regenerate the source file if its producer failed.","Retry the send once the producer has finished writing."],"exampleFix":"// before: send the marker immediately after asking a producer to write the file\nchannel.send(&SendMessage::new(marker_text, to)).await?;\n\n// after: verify the file has content first\nlet len = tokio::fs::metadata(&path).await?.len();\nif len == 0 {\n    anyhow::bail!(\"attachment {} was not written yet\", path.display());\n}\nchannel.send(&SendMessage::new(marker_text, to)).await?;","handlingStrategy":"validation","validationCode":"let len = tokio::fs::metadata(&path).await?.len();\nanyhow::ensure!(len > 0, \"attachment {} is empty; producer may have failed\", path.display());\nchannel.send(&SendMessage::new(marker_text, to)).await","typeGuard":"async fn non_empty_file(path: &std::path::Path) -> bool {\n    matches!(tokio::fs::metadata(path).await, Ok(m) if m.len() > 0)\n}","tryCatchPattern":null,"preventionTips":["Signal file-completion from the producer (temp-file rename pattern) instead of polling paths that may exist empty.","Treat 0-byte artifacts from upstream tools as failures at generation time.","Retry sends whose target file was empty, after confirming the producer finished."],"tags":["whatsapp-web","attachment","file-io","validation","rust"],"backgroundTag":"empty-file","analyzedSha":"88bb9c8533fc57ed7a03e36ca7c9ed2bf8336dcc","analyzedAt":"2026-08-23T01:07:41.857Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}