vitessio/vitess · error
mismatched ShardSession count: originally %d, now %d
Error message
mismatched ShardSession count: originally %d, now %d
What it means
The vitess database/sql driver stores shard sessions returned in session tokens. When a session token passed in contains MORE ShardSessions than the original count recorded when the session was first created, something replaced or regenerated the session token mid-transaction; the driver refuses to commit state that grew beyond what it created, returning this mismatch error.
Source
Thrown at go/vt/vitessdriver/driver.go:360
}
// this is designed to be run after all new work has been done in the tx, similar to
// where you would traditionally run a tx.Commit, to help prevent you from silently
// losing transactional data.
validationFunc := func() error {
var sessionToken string
sessionToken, err = SessionTokenFromTx(ctx, tx)
if err != nil {
return err
}
session, err = sessionTokenToSession(sessionToken)
if err != nil {
return err
}
if len(session.ShardSessions) > originalShardSessionCount {
return fmt.Errorf("mismatched ShardSession count: originally %d, now %d",
originalShardSessionCount, len(session.ShardSessions),
)
}
return nil
}
return tx, validationFunc, nil
}
// SessionTokenFromTx serializes the sessionFromToken on the tx, which can be reconstituted
// into a *sql.Tx using DistributedTxFromSessionToken
func SessionTokenFromTx(ctx context.Context, tx *sql.Tx) (string, error) {
var sessionToken string
err := tx.QueryRowContext(ctx, "vt_session_token").Scan(&sessionToken)
if err != nil {
return "", errView on GitHub (pinned to 01a25a7d17)
Solutions
- Ensure each transaction's session token is used only within that transaction — never reuse or share tokens across transactions or connections.
- Get a fresh session token by beginning a new transaction instead of re-committing an old token.
- If using the driver directly, verify the token passed to Commit originates from the same conn/session that called Begin.
Example fix
// before: token reused across transactions token := tx1.SessionToken() tx2.CommitWithToken(token) // mismatch // after: commit the token of the same transaction token := tx1.SessionToken() tx1.CommitWithToken(token)
Defensive patterns
Strategy: validation
Validate before calling
token := tx.SessionToken()
sess, err := sessionTokenToSession(token)
if err != nil {
return err
}
if len(sess.ShardSessions) != expectedSessionCount {
return fmt.Errorf("token for wrong transaction: %d sessions", len(sess.ShardSessions))
} Type guard
func isShardSessionCountMismatch(err error) bool {
return err != nil && strings.Contains(err.Error(), "mismatched ShardSession count")
} Try / catch
if err := conn.CommitWithToken(token); err != nil {
if isShardSessionCountMismatch(err) {
return fmt.Errorf("session token reused across transactions; start a new transaction: %w", err)
}
return err
} Prevention
- Never share or reuse session tokens across transactions or connections
- Commit only with the token obtained from the same transaction you began
- Avoid copying/stashing tokens in app state that can outlive the transaction
When it happens
Trigger: Calling Commit (via the driver's commit path in vitessdriver) with a session token whose ShardSessions slice length exceeds originalShardSessionCount — typically when a session token from a different transaction/lifetime is committed, or tokens are reused/shared across transactions incorrectly.
Common situations: Application code reusing a session token across transactions or copying it between connections; serialization/deserialization round-trips that merged session states; driver misuse where Begin/Commit is interleaved with tokens from another session.
Related errors
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/7325e7a5202c6fda.
Report an issue: GitHub.