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
- Verify the path targets a file, not a directory: run `ipfs files stat <path>` and check the type before calling file-only commands.
- Re-run the command; if it succeeds the failure was a transient race — serialize concurrent MFS mutations.
- 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
- `ipfs files stat` the path to confirm type=file before file-only commands
- Serialize MFS mutations; avoid concurrent rm/mv/write on the same subtree
- Create parents with `files mkdir -p` so node types are deterministic
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
- expected *mfs.Directory, didn't get it. This is likely a rac
- assets: could load Asset '%s': %s
- pin check failed: %w
- r.String()
- ipfs api address could not be found
AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03).
Data as JSON: /api/errors/377c5b042d30cb5d.
Report an issue: GitHub.