vitessio/vitess · error

[BUG] tried to replace 'Key' on 'VindexParam'

Error message

[BUG] tried to replace 'Key' on 'VindexParam'

What it means

VindexParam.Key is an identifier field that the generated rewriter cannot replace in place; its callback panics on any replacement attempt. Like other identifier fields, keys must be edited by direct assignment rather than node substitution.

Source

Thrown at go/vt/sqlparser/ast_rewrite.go:14558

func (a *application) rewriteVindexParam(parent SQLNode, node VindexParam, replacer replacerFunc) bool {
	if a.pre != nil {
		a.cur.replacer = replacer
		a.cur.parent = parent
		a.cur.node = node
		kontinue := !a.pre(&a.cur)
		if a.cur.revisit {
			a.cur.revisit = false
			return a.rewriteSQLNode(parent, a.cur.node, replacer)
		}
		if kontinue {
			return true
		}
	}
	if a.collectPaths {
		a.cur.current.AddStep(uint16(VindexParamKey))
	}
	if !a.rewriteIdentifierCI(node, node.Key, func(newNode, parent SQLNode) {
		panic("[BUG] tried to replace 'Key' on 'VindexParam'")
	}) {
		return false
	}
	if a.collectPaths {
		a.cur.current.Pop()
	}
	if a.post != nil {
		a.cur.replacer = replacer
		a.cur.parent = parent
		a.cur.node = node
		if !a.post(&a.cur) {
			return false
		}
	}
	return true
}

// Function Generation Source: PtrToStructMethod

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Edit the key by direct assignment: param.Key = sqlparser.NewColIdent(newKey) on the VindexParam node
  2. Return (node, false) from the rewrite callback for identifier fields
  3. Use a dedicated walk over VindexParams rather than the generic path rewriter for parameter renaming
  4. Regenerate code with `make codegen` if generated files are stale

Example fix

// before
// callback: return newKeyNode, true on VindexParam.Key
// after
func repl(node, parent sqlparser.SQLNode) (sqlparser.SQLNode, bool) {
    if param, ok := node.(*sqlparser.VindexParam); ok {
        param.Key = sqlparser.NewColIdent(newKey)
    }
    return node, false
}
Defensive patterns

Strategy: validation

Validate before calling

func repl(node, parent sqlparser.SQLNode) (sqlparser.SQLNode, bool) {
    if param, ok := node.(*sqlparser.VindexParam); ok {
        param.Key = sqlparser.NewColIdent(newKey) // edit in place
        return node, false
    }
    return replaceIfMatched(node)
}

Try / catch

err := func() (err error) {
    defer func() {
        if r := recover(); r != nil {
            err = fmt.Errorf("rewrite panicked on VindexParam.Key: %v", r)
        }
    }()
    return sqlparser.SafeRewrite(ddl, opts, repl)
}()

Prevention

When it happens

Trigger: A rewrite callback returning a replacement node when the visited child is the Key (identifiers.ColIdent) of a *VindexParam inside a VindexDefinition.

Common situations: Rewriters that transform vindex definitions generically; DDL-rewriting tools that alter `CREATE VINDEX ... TYPE ... 'k'='v'` parameters by node replacement.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/9e390f670e18a2b6. Report an issue: GitHub.