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
- Inspect the wrapped %v message to identify the actual panic value and the stack trace printed by the recover path
- Fix the nil-pointer or index bug in the transaction closure that panicked
- If a library panics with a string, convert it to an error at the source or wrap it deliberately with errors.Errorf
- 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
- Never call panic with non-error values in metadata code paths
- Nil-check keys/values before txn operations
- Add -race and panic-recovery tests for txn closures
- Keep the TiKV client library up to date
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
- panic in point get transaction: %v
- The entry of the root inode was not found
- failed to get startTS, which is required for TiKV to ensure
- failed to parse value as int: %v
- unsupported type: %T
AI-assisted analysis of juicedata/juicefs@c9a67b23e8 (2026-09-06).
Data as JSON: /api/errors/b0581e4159917660.
Report an issue: GitHub.