ipfs/kubo · error

either the filestore or the urlstore must be enabled to use

Error message

either the filestore or the urlstore must be enabled to use nocopy, see: https://github.com/ipfs/kubo/blob/master/docs/experimental-features.md#ipfs-filestore

What it means

Add with NoCopy=true imports files without copying bytes into the blockstore, which requires the filestore or urlstore backends that reference external files in place. Both are experimental and disabled by default, so Add refuses the NoCopy option when neither is enabled.

Source

Thrown at core/coreapi/unixfs.go:86

		attribute.Bool("silent", settings.Silent),
		attribute.Bool("progress", settings.Progress),
	)

	cfg, err := api.repo.Config()
	if err != nil {
		return path.ImmutablePath{}, err
	}

	// check if repo will exceed storage limit if added
	// TODO: this doesn't handle the case if the hashed file is already in blocks (deduplicated)
	// TODO: conditional GC is disabled due to it is somehow not possible to pass the size to the daemon
	//if err := corerepo.ConditionalGC(req.Context(), n, uint64(size)); err != nil {
	//	res.SetError(err, cmds.ErrNormal)
	//	return
	//}

	if settings.NoCopy && !(cfg.Experimental.FilestoreEnabled || cfg.Experimental.UrlstoreEnabled) {
		return path.ImmutablePath{}, errors.New("either the filestore or the urlstore must be enabled to use nocopy, see: https://github.com/ipfs/kubo/blob/master/docs/experimental-features.md#ipfs-filestore")
	}

	addblockstore := api.blockstore
	if !(settings.FsCache || settings.NoCopy) {
		addblockstore = bstore.NewGCBlockstore(api.baseBlocks, api.blockstore)
	}
	exch := api.exchange
	pinning := api.pinning

	if settings.OnlyHash {
		// setup a /dev/null pipeline to simulate adding the data
		dstore := dssync.MutexWrap(ds.NewNullDatastore())
		bs := bstore.NewBlockstore(dstore, bstore.WriteThrough(true)) // we use NewNullDatastore, so ok to always WriteThrough when OnlyHash
		addblockstore = bstore.NewGCBlockstore(bs, nil)               // gclocker will never be used
		exch = nil                                                    // exchange will never be used
		pinning = nil                                                 // pinner will never be used
	}

View on GitHub (pinned to 329838acdf)

Solutions

  1. Enable the filestore: `ipfs config --json Experimental.FilestoreEnabled true` and restart the daemon.
  2. Or enable the urlstore: `ipfs config --json Experimental.UrlstoreEnabled true`, if your sources are URLs.
  3. Drop the NoCopy option and let the default blockstore copy the data.
  4. See the linked experimental-features doc for caveats (file moves break the blocks).

Example fix

// before
ipfs add --nocopy bigfile.iso
// after
ipfs config --json Experimental.FilestoreEnabled true && ipfs daemon
ipfs add --nocopy bigfile.iso
Defensive patterns

Strategy: validation

Validate before calling

if useNoCopy {
	cfg, err := api.repoConfig()
	if err != nil {
		return err
	}
	if !cfg.Experimental.FilestoreEnabled && !cfg.Experimental.UrlstoreEnabled {
		return errors.New("nocopy requires FilestoreEnabled or UrlstoreEnabled in config")
	}
}

Try / catch

p, err := api.Unixfs().Add(ctx, file, opts...)
if err != nil && strings.Contains(err.Error(), "filestore or the urlstore must be enabled") {
	// retry without nocopy
	opts = slices.DeleteFunc(opts, isNoCopyOption)
	p, err = api.Unixfs().Add(ctx, file, opts...)
}

Prevention

When it happens

Trigger: Calling Unixfs().Add (or `ipfs add --nocopy`) with settings.NoCopy=true while cfg.Experimental.FilestoreEnabled and UrlstoreEnabled are both false — the default configuration.

Common situations: Users importing large local files with --nocopy on a stock node, library code setting NoCopy assuming the filestore is always available, and DAGs migrated between nodes where the new node lacks the experimental flags.

Related errors


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