ipfs/kubo · error

error listing directory: %w

Error message

error listing directory: %w

What it means

LsIter is a pull-style iterator over UnixFS directory entries. Because iter.Seq2 cannot return a single error, failures (path resolution errors, node fetch errors, blockservice errors) are surfaced as the second yield value; this message is the documented pattern for wrapping them so the 'error listing directory' context is preserved. The library itself just forwards the underlying error from the directory listing operation.

Source

Thrown at core/coreiface/unixfs.go:112

	//	for dirEnt := range dirs {
	//		fmt.Println("Dir name:", dirEnt.Name)
	//	}
	//	err := <-lsErr
	//	if err != nil {
	//		return fmt.Errorf("error listing directory: %w", err)
	//	}
	Ls(context.Context, path.Path, chan<- DirEntry, ...options.UnixfsLsOption) error
}

// LsIter returns a go iterator that allows ranging over DirEntry results.
// Iteration stops if the context is canceled or if the iterator yields an
// error.
//
// Example:
//
//	for dirEnt, err := LsIter(ctx, ufsAPI, p) {
//		if err != nil {
//			return fmt.Errorf("error listing directory: %w", err)
//		}
//		fmt.Println("Dir name:", dirEnt.Name)
//	}
func LsIter(ctx context.Context, api UnixfsAPI, p path.Path, opts ...options.UnixfsLsOption) iter.Seq2[DirEntry, error] {
	return func(yield func(DirEntry, error) bool) {
		ctx, cancel := context.WithCancel(ctx)
		defer cancel() // cancel Ls if done iterating early

		dirs := make(chan DirEntry)
		lsErr := make(chan error, 1)
		go func() {
			lsErr <- api.Ls(ctx, p, dirs, opts...)
		}()
		for dirEnt := range dirs {
			if !yield(dirEnt, nil) {
				return
			}
		}

View on GitHub (pinned to 329838acdf)

Solutions

  1. Check the wrapped underlying error (%w) to identify the true cause (not found vs fetch failure vs not-a-directory)
  2. Verify the path resolves to a directory: use ufs.Stat or ipfs files stat before listing
  3. Ensure the daemon is online and the content is available locally or on the network (ipfs refs local, ipfs dht findprovs)
  4. Handle errors inside the iteration loop exactly as the doc comment shows, wrapping with %w and returning

Example fix

// before
for dirEnt, err := ufs.LsIter(ctx, api, p) {
	if err != nil {
		return fmt.Errorf("error listing directory: %w", err)
	}
	_ = dirEnt
}
// after
stat, serr := ufs.Stat(ctx, p)
if serr != nil {
	return fmt.Errorf("path not found: %w", serr)
}
if stat.Type != FileTypeDirectory {
	return fmt.Errorf("%s is not a directory", p)
}
for dirEnt, err := ufs.LsIter(ctx, api, p) {
	if err != nil {
		return fmt.Errorf("error listing directory: %w", err)
	}
	process(dirEnt)
}
Defensive patterns

Strategy: try-catch

Validate before calling

stat, err := ufs.Stat(ctx, p)
if err != nil { return err }
if stat.Type != FileTypeDirectory { return fmt.Errorf("%s is not a directory", p) }

Type guard

func isDirEntryStat(s *coreiface.Stat) bool { return s != nil && s.Type == coreiface.FileTypeDirectory }

Try / catch

for ent, err := range coreiface.LsIter(ctx, api, p) {
	if err != nil {
		var nfe *NotFoundError
		if errors.As(err, &nfe) { continue } // skip vanished entries
		return fmt.Errorf("error listing directory: %w", err)
	}
	process(ent)
}

Prevention

When it happens

Trigger: Calling LsIter (or Ls) on coreapi.UnixfsAPI with a path that does not exist, is not a UnixFS directory (e.g. a regular file), points to a CID whose blocks cannot be fetched from the network, or continuing to iterate after the context was cancelled.

Common situations: Typo in an IPFS path (/ipfs/<cid>/subdir that doesn't exist); listing a sharded/huge directory offline where peers are unreachable; passing a path to a file instead of a directory; using a context cancelled mid-iteration.

Related errors


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