juicedata/juicefs · error

tikv client txn func error: %v

Error message

tikv client txn func error: %v

What it means

This error is produced by the TikV transaction wrapper in pkg/meta/tkv_tikv.go when the closure passed to the transaction helper panics with a non-error value. The deferred recover() catches the panic; if the recovered value is not an `error`, it wraps it into this formatted error. It signals an unexpected panic inside a TiKV transaction callback rather than a normal transaction failure.

Source

Thrown at pkg/meta/tkv_tikv.go:374

}

func (c *tikvClient) txn(ctx context.Context, f func(*kvTxn) error, retry int) (err error) {
	var opts []tikv.TxnOption
	if val := ctx.Value(txSessionKey{}); val != nil {
		opts = append(opts, tikv.WithStartTS(val.(uint64)))
	}

	tx, err := c.client.Begin(opts...)
	if err != nil {
		return err
	}
	defer func() {
		if r := recover(); r != nil {
			fe, ok := r.(error)
			if ok {
				err = fe
			} else {
				err = errors.Errorf("tikv client txn func error: %v", r)
			}
		}
	}()
	if err = f(&kvTxn{&tikvTxn{tx}, retry}); err != nil {
		return err
	}
	if !tx.IsReadOnly() {
		tx.SetEnable1PC(true)
		tx.SetEnableAsyncCommit(true)
		err = tx.Commit(ctx)
	}
	return err
}

func (c *tikvClient) scan(prefix []byte, handler func(key, value []byte) bool) error {
	end := nextKey(prefix)
	start := prefix
OUT:

View on GitHub (pinned to c9a67b23e8)

Solutions

  1. Inspect the wrapped %v message to identify the actual panic value and the stack trace printed by the recover path
  2. Fix the nil-pointer or index bug in the transaction closure that panicked
  3. If a library panics with a string, convert it to an error at the source or wrap it deliberately with errors.Errorf
  4. Update the TiKV client library if the panic originates inside it and is a known fixed issue

Example fix

// before
panic("bad key format")
// after
return errors.Errorf("bad key format: %q", key)
Defensive patterns

Strategy: try-catch

Validate before calling

// Go: ensure txn closure arguments are non-nil before calling
if key == nil || txn == nil { return errors.New("invalid txn input") }

Type guard

if fe, ok := r.(error); ok { err = fe } else { err = errors.Errorf("tikv client txn func error: %v", r) }

Try / catch

err := doTxn(func(t *kvTxn) error {
    defer func() { if r := recover(); r != nil { err = errors.Errorf("txn panic: %v", r) } }()
    return t.Set(key, val)
})

Prevention

When it happens

Trigger: A transaction closure `f(&kvTxn{...})` panics with a non-error value, e.g. nil pointer dereference, index out of range, or an explicit panic(string) inside code executed via tkv txn on TiKV metadata engine.

Common situations: Bugs in metadata engine code paths (e.g. nil map or slice access while decoding a key), panics from third-party TiKV client libraries during txn commit, or a user-supplied/patched function that panics with a string value instead of an error.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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