golang/go · error

tar: cannot add non-regular file

Error message

tar: cannot add non-regular file

What it means

Returned by Writer.AddFS when walking an fs.FS and encountering a directory entry whose type is neither regular, directory, nor symlink. AddFS intentionally supports only those three kinds (the portable subset); device files, sockets, named pipes, and other special files are refused because they cannot be represented portably in a tar that will be extracted on arbitrary platforms.

Source

Thrown at src/archive/tar/writer.go:426

		if err != nil {
			return err
		}
		if name == "." {
			return nil
		}
		info, err := d.Info()
		if err != nil {
			return err
		}
		linkTarget := ""
		if typ := d.Type(); typ == fs.ModeSymlink {
			var err error
			linkTarget, err = fs.ReadLink(fsys, name)
			if err != nil {
				return err
			}
		} else if !typ.IsRegular() && typ != fs.ModeDir {
			return errors.New("tar: cannot add non-regular file")
		}
		h, err := FileInfoHeader(info, linkTarget)
		if err != nil {
			return err
		}
		h.Name = name
		if d.IsDir() {
			h.Name += "/"
		}
		if err := tw.WriteHeader(h); err != nil {
			return err
		}
		if !d.Type().IsRegular() {
			return nil
		}
		f, err := fsys.Open(name)
		if err != nil {
			return err

View on GitHub (pinned to b6b368adc5)

Solutions

  1. Pre-filter the fs.FS so AddFS only sees regular files, directories, and symlinks — wrap with an fs.FS that skips other types.
  2. Use fs.WalkDir yourself and skip entries where !d.Type().IsRegular() && d.Type() != fs.ModeDir && d.Type() != fs.ModeSymlink.
  3. Stage the content into a clean directory (cp -r without special files) before archiving.
  4. If you must archive special files, write those headers manually with FileInfoHeader (TypeChar/TypeBlock/TypeFifo) — sockets are still unsupported.

Example fix

// before
tw := tar.NewWriter(w)
err := tw.AddFS(os.DirFS("/var/run")) // contains sockets -> throws

// after
tw := tar.NewWriter(w)
err := fs.WalkDir(os.DirFS("src"), ".", func(name string, d fs.DirEntry, err error) error {
  if err != nil { return err }
  t := d.Type()
  if !t.IsRegular() && t != fs.ModeDir && t != fs.ModeSymlink {
    return nil // skip sockets, pipes, devices
  }
  // ... FileInfoHeader + WriteHeader + Copy as in AddFS
  return nil
})
Defensive patterns

Strategy: validation

Validate before calling

err := fs.WalkDir(fsys, ".", func(name string, d fs.DirEntry, err error) error {
  if err != nil { return err }
  t := d.Type()
  if !t.IsRegular() && t != fs.ModeDir && t != fs.ModeSymlink {
    return nil // skip sockets, pipes, devices
  }
  return nil
})

Type guard

func isArchivable(t fs.FileMode) bool {
  return t.IsRegular() || t == fs.ModeDir || t == fs.ModeSymlink
}

Try / catch

if err := tw.AddFS(fsys); err != nil && strings.Contains(err.Error(), "cannot add non-regular file") {
  log.Printf("skipping non-regular files in %v", fsys)
  err = nil
}

Prevention

When it happens

Trigger: Calling tw.AddFS(fsys) where fsys contains a Unix socket, named pipe (FIFO), character/block device, or any other non-regular non-directory non-symlink entry.

Common situations: Archiving a project directory that contains a .git/objects/pack/*.idx socket-like artifact, a docker socket bind-mounted into the tree, a node_modules with FIFOs, or /tmp-like filesystems with sockets; archiving a real OS filesystem (os.DirFS) rather than a clean file tree.

Related errors


AI-assisted analysis of golang/go@b6b368adc5 (2026-08-12). Data as JSON: /api/errors/0006055b6a0ed0a5. Report an issue: GitHub.