a-b-street/abstreet · error

Compressed not there?

Error message

Compressed {} not there?

What it means

After compressing a changed file to a remote path (.gz), the updater reads the compressed file's metadata to record compressed_size_bytes. If the .gz file doesn't exist at that point, it panics — an internal inconsistency, since compress should have just created it.

Solutions

  1. Verify compress() succeeded and wrote to the expected remote_path before reading metadata
  2. Check disk space and write permissions for the remote/compressed output location
  3. Log the underlying io error instead of discarding it to locate the real cause

Example fix

// before
.unwrap_or_else(|_| panic!("Compressed {} not there?", remote_path))
// after
.unwrap_or_else(|e| panic!("Compressed {} not there? {}: {}", remote_path, e, std::backtrace::Backtrace::force_capture()))
Defensive patterns

Strategy: validation

Validate before calling

if !std::path::Path::new(&remote_path).exists() {
    panic!("compress failed to produce {}", remote_path);
}

Prevention

When it happens

Trigger: During upload, fs_err::metadata on `{remote_base}/{path}.gz` fails right after compress() was invoked for a changed file.

Common situations: compress() silently failing (bad permissions, full disk, remote path misconfigured so the .gz lands elsewhere); race with another process cleaning the output directory.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of a-b-street/abstreet@0964f29315 (2026-09-13). Data as JSON: /api/errors/a629dc7fac60f68b. Report an issue: GitHub.

Appendix: source

Thrown at updater/src/main.rs:225

            rm(&format!("{}/{}.gz", remote_base, path));
        }
    }

    // Anything missing or needing updating?
    let local_entries = std::mem::take(&mut local.entries);
    for (path, entry) in Timer::new("compress files").parallelize(
        "compress files",
        local_entries.into_iter().collect(),
        |(path, mut entry)| {
            let remote_path = format!("{}/{}.gz", remote_base, path);
            let changed = remote.entries.get(&path).map(|x| &x.checksum) != Some(&entry.checksum);
            if changed {
                compress(&path, &remote_path);
            }
            // Always do this -- even if nothing changed, compressed_size_bytes isn't filled out by
            // generate_manifest.
            entry.compressed_size_bytes = fs_err::metadata(&remote_path)
                .unwrap_or_else(|_| panic!("Compressed {} not there?", remote_path))
                .len();
            (path, entry)
        },
    ) {
        local.entries.insert(path, entry);
    }

    abstio::write_json(format!("{}/MANIFEST.json", remote_base), &local);
    abstio::write_json("data/MANIFEST.json".to_string(), &local);

    must_run_cmd(
        Command::new("aws")
            .arg("s3")
            .arg("sync")
            .arg("--delete")
            .arg(format!("{}/data", remote_base))
            .arg(format!("s3://abstreet/{}/data", version)),
    );

View on GitHub (pinned to 0964f29315)