{"record":{"id":"9e390f670e18a2b6","repo":"vitessio/vitess","slug":"bug-tried-to-replace-key-on-vindexparam","errorCode":null,"errorMessage":"[BUG] tried to replace 'Key' on 'VindexParam'","messagePattern":"\\[BUG\\] tried to replace 'Key' on 'VindexParam'","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/sqlparser/ast_rewrite.go","lineNumber":14558,"sourceCode":"func (a *application) rewriteVindexParam(parent SQLNode, node VindexParam, replacer replacerFunc) bool {\n\tif a.pre != nil {\n\t\ta.cur.replacer = replacer\n\t\ta.cur.parent = parent\n\t\ta.cur.node = node\n\t\tkontinue := !a.pre(&a.cur)\n\t\tif a.cur.revisit {\n\t\t\ta.cur.revisit = false\n\t\t\treturn a.rewriteSQLNode(parent, a.cur.node, replacer)\n\t\t}\n\t\tif kontinue {\n\t\t\treturn true\n\t\t}\n\t}\n\tif a.collectPaths {\n\t\ta.cur.current.AddStep(uint16(VindexParamKey))\n\t}\n\tif !a.rewriteIdentifierCI(node, node.Key, func(newNode, parent SQLNode) {\n\t\tpanic(\"[BUG] tried to replace 'Key' on 'VindexParam'\")\n\t}) {\n\t\treturn false\n\t}\n\tif a.collectPaths {\n\t\ta.cur.current.Pop()\n\t}\n\tif a.post != nil {\n\t\ta.cur.replacer = replacer\n\t\ta.cur.parent = parent\n\t\ta.cur.node = node\n\t\tif !a.post(&a.cur) {\n\t\t\treturn false\n\t\t}\n\t}\n\treturn true\n}\n\n// Function Generation Source: PtrToStructMethod","sourceCodeStart":14540,"sourceCodeEnd":14576,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/sqlparser/ast_rewrite.go#L14540-L14576","documentation":"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.","triggerScenarios":"A rewrite callback returning a replacement node when the visited child is the Key (identifiers.ColIdent) of a *VindexParam inside a VindexDefinition.","commonSituations":"Rewriters that transform vindex definitions generically; DDL-rewriting tools that alter `CREATE VINDEX ... TYPE ... 'k'='v'` parameters by node replacement.","solutions":["Edit the key by direct assignment: param.Key = sqlparser.NewColIdent(newKey) on the VindexParam node","Return (node, false) from the rewrite callback for identifier fields","Use a dedicated walk over VindexParams rather than the generic path rewriter for parameter renaming","Regenerate code with `make codegen` if generated files are stale"],"exampleFix":"// before\n// callback: return newKeyNode, true on VindexParam.Key\n// after\nfunc repl(node, parent sqlparser.SQLNode) (sqlparser.SQLNode, bool) {\n    if param, ok := node.(*sqlparser.VindexParam); ok {\n        param.Key = sqlparser.NewColIdent(newKey)\n    }\n    return node, false\n}","handlingStrategy":"validation","validationCode":"func repl(node, parent sqlparser.SQLNode) (sqlparser.SQLNode, bool) {\n    if param, ok := node.(*sqlparser.VindexParam); ok {\n        param.Key = sqlparser.NewColIdent(newKey) // edit in place\n        return node, false\n    }\n    return replaceIfMatched(node)\n}","typeGuard":null,"tryCatchPattern":"err := func() (err error) {\n    defer func() {\n        if r := recover(); r != nil {\n            err = fmt.Errorf(\"rewrite panicked on VindexParam.Key: %v\", r)\n        }\n    }()\n    return sqlparser.SafeRewrite(ddl, opts, repl)\n}()","preventionTips":["Edit VindexParam keys by direct field assignment","Never replace identifier nodes via rewriter callbacks","Cover CREATE/ALTER VINDEX DDL in rewriter tests"],"tags":["sqlparser","ast-rewrite","codegen","panic","identifiers"],"backgroundTag":"invalid-ast-rewrite-replacement","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}