juicedata/juicefs · error

prefix must be nil, but got %v

Error message

prefix must be nil, but got %v

What it means

prefixClient wraps a tkvClient and scopes all keys under a prefix. Its reset() intentionally only accepts nil: the wrapper always resets the whole underlying client using its own prefix, so passing a non-nil prefix is treated as an API misuse and rejected with this error.

Source

Thrown at pkg/meta/tkv_prefix.go:120

func (c *prefixClient) txn(ctx context.Context, f func(*kvTxn) error, retry int) error {
	return c.tkvClient.txn(ctx, func(tx *kvTxn) error {
		return f(&kvTxn{&prefixTxn{tx, c.prefix}, retry})
	}, retry)
}

func (c *prefixClient) scan(prefix []byte, handler func(key, value []byte) bool) error {
	k := make([]byte, len(c.prefix)+len(prefix))
	copy(k, c.prefix)
	copy(k[len(c.prefix):], prefix)
	return c.tkvClient.scan(k, func(key, value []byte) bool {
		return handler(key[len(c.prefix):], value)
	})
}

func (c *prefixClient) reset(prefix []byte) error {
	if prefix != nil {
		return fmt.Errorf("prefix must be nil, but got %v", prefix)
	}
	return c.tkvClient.reset(c.prefix)
}

func (c *prefixClient) logKey(m *kvMeta, id uint64) []byte {
	if cc, ok := c.tkvClient.(tkvChangelogClient); ok {
		return cc.logKey(m, id)
	}
	return m.fmtKey("XLOG", id)
}

func (c *prefixClient) scanLogRange(m *kvMeta, tx *kvTxn, beginID, endID uint64, keysOnly bool, handler func(id uint64, k, v []byte) bool) {
	if cc, ok := c.tkvClient.(tkvChangelogClient); ok {
		cc.scanLogRange(m, tx, beginID, endID, keysOnly, handler)
		return
	}
	tx.scan(m.fmtKey("XLOG", beginID), m.fmtKey("XLOG", endID), keysOnly, func(k, v []byte) bool {
		return handler(binary.BigEndian.Uint64(k[4:]), k, v)

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Call reset(nil) on the prefixClient — the wrapper applies its own prefix to the underlying reset
  2. If you need to reset a sub-range, reset the raw underlying tkvClient with that prefix instead of the wrapper
  3. Fix shared test reset helpers to special-case prefixClient (or type-assert to it) and always pass nil

Example fix

// before
err := prefixCli.reset([]byte("test/"))
// after
err := prefixCli.reset(nil)
Defensive patterns

Strategy: validation

Validate before calling

if pfx, ok := cli.(interface{ reset([]byte) error }); ok { _ = pfx.reset(nil) } // prefixClient.reset only accepts nil

Prevention

When it happens

Trigger: Calling reset(somePrefix) on a *prefixClient obtained from tkv_prefix.go (e.g. in tests or engine glue) instead of reset(nil).

Common situations: Test helpers that share a reset helper across raw tkv clients and prefix-wrapped clients; code migrated from a raw tkvClient that still passes a prefix argument.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06). Data as JSON: /api/errors/6c1fec0dd2dda5f1. Report an issue: GitHub.