screenpipe/screenpipe · error

VIDEO_CORRUPTED: file too small ({} bytes) {}

Error message

VIDEO_CORRUPTED: file too small ({} bytes) {}

What it means

Files smaller than 1024 bytes cannot hold a valid video container (no moov/ftyp atoms of substance), so the function treats them as corrupted before wasting an ffmpeg spawn, using the same VIDEO_CORRUPTED prefix mapped to 410 by the HTTP route.

Source

Thrown at crates/screenpipe-engine/src/video_utils.rs:1122

pub async fn extract_frame_from_video(
    file_path: &str,
    offset_index: i64,
    jpeg_quality: &str,
) -> Result<String> {
    if offset_index < 0 {
        return Err(anyhow::anyhow!(
            "invalid negative frame index: {}",
            offset_index
        ));
    }
    let metadata = ensure_regular_media_file(file_path).await?;
    if metadata.len() == 0 {
        return Err(anyhow::anyhow!("VIDEO_CORRUPTED: empty file {}", file_path));
    }
    // Files under 1KB are likely corrupted (no valid video that small).
    if metadata.len() < 1024 {
        return Err(anyhow::anyhow!(
            "VIDEO_CORRUPTED: file too small ({} bytes) {}",
            metadata.len(),
            file_path
        ));
    }

    let ffmpeg_path =
        find_ffmpeg_path().ok_or_else(|| anyhow::anyhow!("failed to find ffmpeg path"))?;

    // A file whose metadata will not parse is still worth one extraction
    // attempt, but if that attempt also fails the file is unreadable rather
    // than merely awkward — the route maps that to 410 instead of 500.
    let metadata = probe_frame_metadata(&ffmpeg_path, file_path).await?;
    let metadata_unreadable = metadata.is_none();
    let locator = plan_frame_locator(file_path, offset_index, metadata);

    // Create a temporary directory for frames if it doesn't exist
    let frames_dir = PathBuf::from("/tmp/screenpipe_frames");

View on GitHub (pinned to 4ebf712990)

Solutions

  1. Delete/quarantine the undersized file; it is unrecoverable as video
  2. Regenerate the segment by re-recording
  3. Investigate the writer path (disk space, abrupt shutdown) if many such files appear
  4. Sweep the media directory at startup for files < 1KB
Defensive patterns

Strategy: validation

Validate before calling

fn looks_like_video(path: &str) -> bool {
    std::fs::metadata(path).map(|m| m.len() >= 1024).unwrap_or(false)
}

Try / catch

match extract_frame_from_video(&path, idx, "2").await {
    Ok(jpeg) => jpeg,
    Err(e) if e.to_string().starts_with("VIDEO_CORRUPTED") => None, // mark file dead
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: extract_frame_from_video (or its callers generate_thumbnail / try_extract_and_serve_frame / run_frame_ocr) is given a regular file whose metadata.len() is between 1 and 1023 bytes.

Common situations: Same truncation causes as the empty-file case but partially written: crash after writing only the header, interrupted flush, tiny placeholder files from a sync client.

Related errors


AI-assisted analysis of screenpipe/screenpipe@4ebf712990 (2026-09-01). Data as JSON: /api/errors/e9763b66ef8b1f50. Report an issue: GitHub.