{"record":{"id":"e5f21cf6e565a0a2","repo":"screenpipe/screenpipe","slug":"export-produced-an-empty-file","errorCode":null,"errorMessage":"export produced an empty file","messagePattern":"export produced an empty file","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/screenpipe-engine/src/meeting_export.rs","lineNumber":385,"sourceCode":"    tokio::fs::write(&concat_path, concat_body)\n        .await\n        .context(\"failed to write concat list\")?;\n\n    if let Some(parent) = output_path.parent() {\n        tokio::fs::create_dir_all(parent)\n            .await\n            .with_context(|| format!(\"failed to create output dir {}\", parent.display()))?;\n    }\n\n    // 8. Single ffmpeg mux: concat (video) + N audio inputs → re-timed video + mixed audio.\n    run_mux(&ffmpeg_path, &concat_path, &audio, origin, output_path).await?;\n\n    let file_size_bytes = tokio::fs::metadata(output_path)\n        .await\n        .map(|m| m.len())\n        .unwrap_or(0);\n    if file_size_bytes == 0 {\n        return Err(anyhow!(\"export produced an empty file\"));\n    }\n\n    let summary = MeetingExportSummary {\n        output_path: output_path.to_string_lossy().to_string(),\n        frame_count: surviving.len(),\n        audio_chunk_count: audio.len(),\n        duration_secs: timeline_end,\n        file_size_bytes,\n    };\n    info!(\n        \"export complete: {} frames, {} audio chunks, {:.1}s, {} bytes -> {}\",\n        summary.frame_count,\n        summary.audio_chunk_count,\n        summary.duration_secs,\n        summary.file_size_bytes,\n        summary.output_path\n    );\n    Ok(summary)","sourceCodeStart":367,"sourceCodeEnd":403,"githubUrl":"https://github.com/screenpipe/screenpipe/blob/4ebf712990fee17eeaf904dacf749b6e96ac9bf3/crates/screenpipe-engine/src/meeting_export.rs#L367-L403","documentation":"After running the ffmpeg mux pipeline, the export routine stats the output MP4 and rejects it if its size is 0 bytes. An empty output means the mux produced no data — usually ffmpeg ran 'successfully' but consumed no valid frames/audio inputs. This is a post-flight sanity check so callers never receive a corrupt/empty file path.","triggerScenarios":"Calling export_range_to_mp4 or export_range_to_mp4_video_only when the selected frame range has no surviving frames, all source video files referenced by the frames are missing or truncated (0-byte), or ffmpeg's concat/mux steps produced an output file that was never written (e.g. disk full or output path unwritable so metadata.len() is 0).","commonSituations":"User asks to export a meeting window that was pruned to zero frames after dedup/snapshot filtering; video files were deleted by retention/cleanup before export; output disk ran out of space mid-write; output path points to a directory or locked file so ffmpeg wrote nothing.","solutions":["Check that surviving frames reference existing, non-empty source video files before calling export (disk existence + size > 0).","Widen the requested time range or reduce filtering so at least one frame survives export.","Verify free disk space and write permissions on output_path.","Run the export again with ffmpeg stderr logging enabled to see warnings from the mux steps."],"exampleFix":"// before\nlet summary = export_range_to_mp4(&state, range, out_path).await?;\n// after\nif !range_has_surviving_frames(&state, &range).await? {\n    return Err(anyhow!(\"no frames in the requested range; nothing to export\"));\n}\nlet summary = export_range_to_mp4(&state, range, out_path).await?;","handlingStrategy":"validation","validationCode":"use std::path::Path;\nfn validate_export_inputs(frames: &[FrameRef]) -> Result<(), String> {\n    if frames.is_empty() { return Err(\"no frames in range\".into()); }\n    for f in frames {\n        let p = Path::new(&f.video_path);\n        match std::fs::metadata(p) {\n            Ok(m) if m.len() > 0 => {}\n            Ok(_) => return Err(format!(\"empty source video: {}\", f.video_path)),\n            Err(_) => return Err(format!(\"missing source video: {}\", f.video_path)),\n        }\n    }\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pre-check that every frame's source video exists and is non-empty before exporting.","Reject time ranges that filter down to zero frames.","Check free disk space on the output volume before starting an export.","Log ffmpeg stderr during export to diagnose empty-output runs."],"tags":["ffmpeg","export","empty-output","mp4"],"backgroundTag":"empty-output-file","analyzedSha":"4ebf712990fee17eeaf904dacf749b6e96ac9bf3","analyzedAt":"2026-09-01T23:33:43.065Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}