ipfs/kubo · error
file is not regular
Error message
file is not regular
What it means
`ipfs get --compress` without `--archive` streams the fetched node as a single gzip-compressed file. This only works when the node is a regular UnixFS file; when the node is a directory (or another non-file node), `files.ToFile(f)` returns nil and `fileArchive` fails with 'file is not regular'. Directories must be wrapped in a tar archive first.
Source
Thrown at core/commands/get.go:326
if checkErrAndClosePipe(err) {
return nil, err
}
closeGzwAndPipe := func() {
if err := maybeGzw.Close(); checkErrAndClosePipe(err) {
return
}
if err := bufw.Flush(); checkErrAndClosePipe(err) {
return
}
pipew.Close() // everything seems to be ok.
}
if !archive && compression != gzip.NoCompression {
// the case when the node is a file
r := files.ToFile(f)
if r == nil {
return nil, errors.New("file is not regular")
}
go func() {
if _, err := io.Copy(maybeGzw, r); checkErrAndClosePipe(err) {
return
}
closeGzwAndPipe() // everything seems to be ok
}()
} else {
// the case for 1. archive, and 2. not archived and not compressed, in
// which tar is used anyway as a transport format
// construct the tar writer
w, err := files.NewTarWriter(maybeGzw)
if checkErrAndClosePipe(err) {
return nil, err
}
View on GitHub (pinned to 329838acdf)
Solutions
- Add `--archive=true` so the node is tarred before compression (produces .tar.gz).
- Drop `--compress` to get the plain (uncompressed) output directory.
- Verify the target is a regular file CID, not a directory CID (e.g. via `ipfs files stat` or `ipfs ls`).
Example fix
// before ipfs get QmDirCID --compress // after ipfs get QmDirCID --archive --compress # yields QmDirCID.tar.gz
Defensive patterns
Strategy: validation
Validate before calling
// resolve the node type before fetching with compression
if out, err := sh.Request("files", "stat", cid).Option("format", "unixfs").Send(ctx); err == nil {
if typ, _ := out.Response.Decode().Get("Type").String(); typ == "directory" {
useArchive = true // directories need --archive --compress
}
} Try / catch
out, err := sh.Request("get", cid).Option("compress", true).Send(ctx)
if err != nil && strings.Contains(err.Error(), "file is not regular") {
// retry as tar.gz
out, err = sh.Request("get", cid).Option("archive", true).Option("compress", true).Send(ctx)
} Prevention
- Pass --archive together with --compress whenever the target may be a directory
- Check the node type with `ipfs files stat` or `ipfs ls` before choosing flags
- Remember gzip cannot encode directory structure; tar must come first
When it happens
Trigger: `ipfs get <cid-of-directory> --compress` (no `--archive`); also any non-regular node such as a raw directory DAG fetched with compression enabled and archive=false.
Common situations: User downloads a directory CID and adds only `--compress`, not realizing gzip cannot represent a directory tree; scripting a generic download helper that always passes `--compress`; HAMT-sharded directories that look like files by name but are directories in the DAG.
Related errors
- %s can't be used with UnixFS metadata like mode or modificat
- option %q requires %q to be provided as well
- file does not support seeking
- unrecognized node type: %s
- cp: source must be a valid UnixFS (dag-pb or raw codec)
AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03).
Data as JSON: /api/errors/b181ce446b90020f.
Report an issue: GitHub.