ipfs/kubo · error

reached limit of %d unflushed MFS operations. To resolve: 1)

Error message

reached limit of %d unflushed MFS operations. To resolve: 1) run 'ipfs files flush' to persist changes, 2) use --flush=true (default), or 3) increase Internal.MFSNoFlushLimit in config

What it means

Error "reached limit of %d unflushed MFS operations. To resolve: 1) run 'ipfs files flush' to persist changes, 2) use --flush=true (default), or 3) increase Internal.MFSNoFlushLimit in config" thrown in ipfs/kubo.

Source

Thrown at core/commands/files.go:73

// updateNoFlushCounter manages the counter for unflushed operations
func updateNoFlushCounter(nd *core.IpfsNode, flush bool) error {
	if flush {
		// Reset counter when flushing
		noFlushOperationCounter.Store(0)
		return nil
	}

	// Cache the limit on first use (config doesn't change at runtime)
	noFlushLimitInit.Do(func() {
		noFlushLimit = int64(config.DefaultMFSNoFlushLimit)
		if cfg, err := nd.Repo.Config(); err == nil && cfg.Internal.MFSNoFlushLimit != nil {
			noFlushLimit = cfg.Internal.MFSNoFlushLimit.WithDefault(int64(config.DefaultMFSNoFlushLimit))
		}
	})

	// Check if limit reached
	if noFlushLimit > 0 && noFlushOperationCounter.Load() >= noFlushLimit {
		return fmt.Errorf("reached limit of %d unflushed MFS operations. "+
			"To resolve: 1) run 'ipfs files flush' to persist changes, "+
			"2) use --flush=true (default), or "+
			"3) increase Internal.MFSNoFlushLimit in config", noFlushLimit)
	}

	noFlushOperationCounter.Add(1)
	return nil
}

// mfsPinLock takes the pin lock, a shared read-lock on the blockstore GC
// locker. A concurrent "ipfs repo gc" holds the exclusive GC lock, so while
// this lock is held GC cannot run, and GC waits for it to be released. Hold it
// across a whole MFS mutation (including its flush) so GC cannot collect blocks
// the mutation has written to the blockstore before they are linked into the
// persisted MFS root. This mirrors how "ipfs add" guards its writes.
func mfsPinLock(nd *core.IpfsNode, ctx context.Context) bstore.Unlocker {
	return nd.Blockstore.PinLock(ctx)
}

View on GitHub (pinned to 329838acdf)

Solutions

  1. Run 'ipfs files flush' to persist pending changes and reset the counter
  2. Omit --flush=false so operations flush by default
  3. Raise Internal.MFSNoFlushLimit in the config if the workload legitimately needs more unflushed operations
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at core/commands/files.go:73 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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