ipfs/kubo · error

expected *mfs.File, didn't get it. This is likely a race con

Error message

expected *mfs.File, didn't get it. This is likely a race condition

What it means

getFileHandle in core/commands/files.go performs an unchecked type assertion of an mfs.FSNode to *mfs.File. If the node at the requested path is not a plain file (e.g. a directory or other FSNode type), or if the MFS tree was concurrently modified between lookup and assertion, the assertion fails and this error is returned instead of panicking.

Source

Thrown at core/commands/files.go:1571

		nd := dag.NodeWithData(ft.FilePBData(nil, 0))
		err = nd.SetCidBuilder(builder)
		if err != nil {
			return nil, err
		}
		err = pdir.AddChild(fname, nd)
		if err != nil {
			return nil, err
		}

		fsn, err := pdir.Child(fname)
		if err != nil {
			return nil, err
		}

		fi, ok := fsn.(*mfs.File)
		if !ok {
			return nil, errors.New("expected *mfs.File, didn't get it. This is likely a race condition")
		}
		return fi, nil

	default:
		return nil, err
	}
}

func checkPath(p string) (string, error) {
	if len(p) == 0 {
		return "", fmt.Errorf("paths must not be empty")
	}

	if p[0] != '/' {
		return "", fmt.Errorf("paths must start with a leading slash")
	}

	cleaned := gopath.Clean(p)

View on GitHub (pinned to 329838acdf)

Solutions

  1. Verify the path targets a file, not a directory: run `ipfs files stat <path>` and check the type before calling file-only commands.
  2. Re-run the command; if it succeeds the failure was a transient race — serialize concurrent MFS mutations.
  3. Use MFS operations that accept directories (e.g. `files ls`) if the target is a directory.

Example fix

// before: blind call
ipfs files read /some/path
// after: stat first
if [ "$(ipfs files stat --format="<type>" /some/path)" = "file" ]; then
  ipfs files read /some/path
fi
Defensive patterns

Strategy: type-guard

Validate before calling

type=$(ipfs files stat --format='<type>' "$P") ; [ "$type" = "file" ] || echo "not a file"

Type guard

if f, ok := fsn.(*mfs.File); ok { return f, nil }
return nil, fmt.Errorf("path %s is not a regular file", name)

Try / catch

fi, err := getFileHandle(node, name)
if err != nil {
    if strings.Contains(err.Error(), "expected *mfs.File") { /* retry after re-stat or report wrong node type */ }
    return err
}

Prevention

When it happens

Trigger: Calling a files API command (e.g. `ipfs files read`, `files write`) whose handler resolves a path via getFileHandle when (1) the path actually points to a directory rather than a file, or (2) another concurrent mutation (rm/mv/chmod/write) replaces the node between the MFS lookup and the type assertion.

Common situations: Scripts running `ipfs files read` on a path that a concurrent `ipfs files rm`/`files mv` just replaced; pointing a write command at a directory path by mistake; parallel tooling mutating MFS while another command holds the path.

Related errors


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