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

  1. Add `--archive=true` so the node is tarred before compression (produces .tar.gz).
  2. Drop `--compress` to get the plain (uncompressed) output directory.
  3. 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

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


AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03). Data as JSON: /api/errors/b181ce446b90020f. Report an issue: GitHub.