ipfs/kubo · error
expected at least one child dir, got none
Error message
expected at least one child dir, got none
What it means
When AddAllAndPin finishes importing a root that is a directory, it tries to unwrap a single-child root so the final CID addresses the child directly (flattening redundant single-entry directory wrappers). If ListNames on the root directory returns zero children, it errors instead of producing a CID for an empty directory wrapper it cannot flatten. In practice this surfaces when the root directory contains no entries at all.
Source
Thrown at core/coreunix/add.go:345
root = rootdir
err = root.Flush()
if err != nil {
return nil, err
}
// if adding a file without wrapping, swap the root to it (when adding a
// directory, mfs root is the directory)
_, dir := file.(files.Directory)
var name string
if !dir {
children, err := rootdir.ListNames(adder.ctx)
if err != nil {
return nil, err
}
if len(children) == 0 {
return nil, fmt.Errorf("expected at least one child dir, got none")
}
// Replace root with the first child
name = children[0]
root, err = rootdir.Child(name)
if err != nil {
return nil, err
}
}
err = mr.Close()
if err != nil {
return nil, err
}
nd, err := root.GetNode()
if err != nil {
return nil, errView on GitHub (pinned to 329838acdf)
Solutions
- Add at least one entry to the directory root before calling AddAllAndPin
- If you intentionally want an empty-directory CID, use a different API path (e.g. construct the UnixFS dir node directly or use files/MFS APIs) rather than AddAllAndPin
- Check hidden-file filters (.hide options) that may be excluding every entry
- Verify the source directory passed to files.NewSerialFile is not empty
Example fix
// before: empty root
empty := files.NewMapFile("", "", map[string]files.Node{})
adder.AddAllAndPin(ctx, empty, true) // expected at least one child dir, got none
// after: include at least one child
entry := files.NewBytesFile([]byte("hello"))
root := files.NewMapFile("", "", map[string]files.Node{"hello.txt": entry})
adder.AddAllAndPin(ctx, root, true) Defensive patterns
Strategy: validation
Validate before calling
names, err := rootdir.ListNames(ctx)
if err != nil { return err }
if len(names) == 0 {
return errors.New("refusing to AddAllAndPin an empty directory root")
} Try / catch
if err := adder.AddAllAndPin(ctx, root, true); err != nil {
if strings.Contains(err.Error(), "expected at least one child dir") {
// fall back to constructing an empty-dir UnixFS node directly
}
return err
} Prevention
- Check the source directory is non-empty before ipfs add -r
- Re-review hidden-file filter settings that can exclude all entries
- When constructing files.NewMapFile roots, assert the map has at least one entry
- Decide explicitly how empty-directory imports should be represented and use a dedicated API if needed
When it happens
Trigger: Calling Adder.AddAllAndPin on a files.Directory root that ends up with no named children — e.g. files.NewMapFile("", "", map[string]files.Node{}) or a SerialFile walk over an empty directory — where the flattening path ListNames returns an empty list.
Common situations: Importing an empty directory via ipfs add -r; constructing map/slice file roots programmatically and forgetting to add entries; filtering out all entries (e.g. hidden-file filters with everything excluded) before adding.
Related errors
- unrecognized fsn type: %#v
- unknown file type
- unknown layout: %d
- unsupported file type '%s'
- file type %d not supported
AI-assisted analysis of ipfs/kubo@329838acdf (2026-09-03).
Data as JSON: /api/errors/a1fa9641a0adaf9d.
Report an issue: GitHub.