{"record":{"id":"b181ce446b90020f","repo":"ipfs/kubo","slug":"file-is-not-regular","errorCode":null,"errorMessage":"file is not regular","messagePattern":"file is not regular","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/commands/get.go","lineNumber":326,"sourceCode":"\tif checkErrAndClosePipe(err) {\n\t\treturn nil, err\n\t}\n\n\tcloseGzwAndPipe := func() {\n\t\tif err := maybeGzw.Close(); checkErrAndClosePipe(err) {\n\t\t\treturn\n\t\t}\n\t\tif err := bufw.Flush(); checkErrAndClosePipe(err) {\n\t\t\treturn\n\t\t}\n\t\tpipew.Close() // everything seems to be ok.\n\t}\n\n\tif !archive && compression != gzip.NoCompression {\n\t\t// the case when the node is a file\n\t\tr := files.ToFile(f)\n\t\tif r == nil {\n\t\t\treturn nil, errors.New(\"file is not regular\")\n\t\t}\n\n\t\tgo func() {\n\t\t\tif _, err := io.Copy(maybeGzw, r); checkErrAndClosePipe(err) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tcloseGzwAndPipe() // everything seems to be ok\n\t\t}()\n\t} else {\n\t\t// the case for 1. archive, and 2. not archived and not compressed, in\n\t\t// which tar is used anyway as a transport format\n\n\t\t// construct the tar writer\n\t\tw, err := files.NewTarWriter(maybeGzw)\n\t\tif checkErrAndClosePipe(err) {\n\t\t\treturn nil, err\n\t\t}\n","sourceCodeStart":308,"sourceCodeEnd":344,"githubUrl":"https://github.com/ipfs/kubo/blob/329838acdfafae224582930457efe80aa217afc0/core/commands/get.go#L308-L344","documentation":"`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.","triggerScenarios":"`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.","commonSituations":"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.","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`)."],"exampleFix":"// before\nipfs get QmDirCID --compress\n// after\nipfs get QmDirCID --archive --compress  # yields QmDirCID.tar.gz","handlingStrategy":"validation","validationCode":"// resolve the node type before fetching with compression\nif out, err := sh.Request(\"files\", \"stat\", cid).Option(\"format\", \"unixfs\").Send(ctx); err == nil {\n    if typ, _ := out.Response.Decode().Get(\"Type\").String(); typ == \"directory\" {\n        useArchive = true // directories need --archive --compress\n    }\n}","typeGuard":null,"tryCatchPattern":"out, err := sh.Request(\"get\", cid).Option(\"compress\", true).Send(ctx)\nif err != nil && strings.Contains(err.Error(), \"file is not regular\") {\n    // retry as tar.gz\n    out, err = sh.Request(\"get\", cid).Option(\"archive\", true).Option(\"compress\", true).Send(ctx)\n}","preventionTips":["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"],"tags":["cli","unixfs","compression","tar"],"backgroundTag":"not-a-regular-file","analyzedSha":"329838acdfafae224582930457efe80aa217afc0","analyzedAt":"2026-09-03T18:30:52.135Z","contentChangedAt":"2026-09-03T18:30:52.135Z","schemaVersion":2},"datasetVersion":"2026-09-11T00:17:11.886Z"}