ipfs/kubo · error

cp: cannot unlink existing file: %s

Error message

cp: cannot unlink existing file: %s

What it means

`ipfs files cp --force` first unlinks an existing destination entry via unlinkNodeIfExists before placing the new node; this error wraps a failure during that unlink step. It means MFS could not remove the existing entry at dst (see errors 278/279 raised by the helper for the specific causes).

Source

Thrown at core/commands/files.go:585

		mkParents, _ := req.Options[filesParentsOptionName].(bool)
		if mkParents {
			maxDirLinks := int(cfg.Import.UnixFSDirectoryMaxLinks.WithDefault(config.DefaultUnixFSDirectoryMaxLinks))
			sizeEstimationMode := cfg.Import.HAMTSizeEstimationMode()
			err := ensureContainingDirectoryExists(nd.FilesRoot, dst,
				mfs.WithCidBuilder(prefix),
				mfs.WithMaxLinks(maxDirLinks),
				mfs.WithSizeEstimationMode(sizeEstimationMode),
			)
			if err != nil {
				return err
			}
		}

		force, _ := req.Options[forceOptionName].(bool)
		if force {
			if err = unlinkNodeIfExists(nd, dst); err != nil {
				return fmt.Errorf("cp: cannot unlink existing file: %s", err)
			}
		}

		flush, _ := req.Options[filesFlushOptionName].(bool)

		if err := updateNoFlushCounter(nd, flush); err != nil {
			return err
		}

		err = mfs.PutNode(nd.FilesRoot, dst, node)
		if err != nil {
			return fmt.Errorf("cp: cannot put node in path %s: %s", dst, err)
		}
		if flush {
			if _, err := mfs.FlushPath(req.Context, nd.FilesRoot, dst); err != nil {
				return fmt.Errorf("cp: cannot flush the created file %s: %s", dst, err)
			}
			// Flush parent to clear directory cache and free memory.

View on GitHub (pinned to 329838acdf)

Solutions

  1. Check what exists at dst with `ipfs files stat <dst>`; --force only unlinks existing files, not directories
  2. Remove directories manually first: `ipfs files rm -r <dst>` then run cp without --force
  3. Verify every component of the dst path except the last is a directory: `ipfs files ls <parent>`
  4. Create missing parent directories with `ipfs files mkdir -p <parent>`

Example fix

// before: dst is a directory, cp --force cannot unlink it
ipfs files cp --force /ipfs/Qm... /my-dir
// error: cp: cannot unlink existing file: not a file: /my-dir

// after
ipfs files rm -r /my-dir
ipfs files cp /ipfs/Qm... /my-dir
Defensive patterns

Strategy: validation

Validate before calling

// ensure parent dirs exist and dst is not a directory before cp --force
run("ipfs", "files", "mkdir", "-p", filepath.Dir(dst))
if statType(dst) == "directory" {
    run("ipfs", "files", "rm", "-r", dst)
}

Type guard

func isExistingDirectory(dst string) bool {
    out, err := run("ipfs", "files", "stat", dst)
    return err == nil && strings.Contains(out, "directory")
}

Try / catch

if err := ipfsFilesCpForce(src, dst); err != nil {
    if strings.Contains(err.Error(), "cannot unlink existing file") {
        // inspect dst type; rm -r if directory, then retry
    }
}

Prevention

When it happens

Trigger: Running `ipfs files cp --force <src> <dst>` where dst exists and unlinkNodeIfExists fails — e.g. the dst parent path component is not a directory, the existing child is itself a directory (not a TFile), or the MFS root is in a broken state.

Common situations: Using --force to overwrite a dst that is a directory; dst path contains a file as an intermediate component (`/a.txt/b`); MFS concurrently modified so parent lookup fails.

Related errors


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