Skip to content
Latchkey

How actions/cache Uses tar and zstd Internally

GitHub Actions caching is tar plus a compressor under the hood, usually zstd.

When a cache restore or save fails, the error is almost always a tar error. Understanding what actions/cache runs makes those log lines readable.

What it does

The actions/cache toolkit packs the configured paths into a tar archive and compresses it, preferring zstd when the zstd binary is available on the runner and falling back to gzip otherwise. On restore it downloads that archive and extracts it with tar. The cache key plus the runner OS determine which archive you get back.

What it runs (conceptually)

Conceptual
# Save (simplified): tar the paths, pipe through zstd
tar --posix -cf cache.tzst --use-compress-program 'zstd -T0' -P -C <workspace> <paths>
# Restore: stream the archive back through tar
zstd -d -c cache.tzst | tar -xf - -P -C <workspace>

Notes

AspectBehavior
Compressorzstd if present, else gzip
Archive name.tzst (zstd) or .tgz (gzip)
-P / --absolute-namesUsed so absolute cached paths round-trip
Cross-OSA Linux cache may not restore cleanly on Windows/macOS
GNU vs BSDmacOS runners use bsdtar; metadata can differ

In CI

Because the cache is a tar+zstd archive, a runner missing zstd, a near-full disk, or a path that vanished between save and restore all surface as tar or zstd errors in the cache step. Keep the cached paths stable and the runner image consistent across jobs that share a key.

Common errors in CI

Warning: Tar failed with error: ... in a cache step usually wraps a real tar message like tar: <path>: Cannot open: No such file or directory (the path did not exist at save time) or a zstd write error on a full disk. /usr/bin/tar: Cannot use compressed or remote archives points at a tar too old for the requested filter. The cache silently no-ops on these so the job continues uncached.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →