{"record":{"id":"47d26931379013e6","repo":"vitessio/vitess","slug":"execnoprepare-unexpected-error-v","errorCode":null,"errorMessage":"ExecNoPrepare unexpected error: %+v","messagePattern":"ExecNoPrepare unexpected error: %\\+v","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/external/golib/sqlutils/sqlutils.go","lineNumber":249,"sourceCode":"\n\tvar rows *sql.Rows\n\trows, err = db.Query(query, args...)\n\tif rows != nil {\n\t\tdefer rows.Close()\n\t}\n\tif err != nil && err != sql.ErrNoRows {\n\t\tlog.Error(fmt.Sprint(err))\n\t\treturn err\n\t}\n\terr = ScanRowsToMaps(rows, on_row)\n\treturn\n}\n\n// ExecNoPrepare executes given query using given args on given DB, without using prepared statements.\nfunc ExecNoPrepare(db *sql.DB, query string, args ...any) (res sql.Result, err error) {\n\tdefer func() {\n\t\tif derr := recover(); derr != nil {\n\t\t\terr = fmt.Errorf(\"ExecNoPrepare unexpected error: %+v\", derr)\n\t\t}\n\t}()\n\n\tres, err = db.Exec(query, args...)\n\tif err != nil {\n\t\tlog.Error(fmt.Sprint(err))\n\t}\n\treturn res, err\n}\n\n// Convert variable length arguments into arguments array\nfunc Args(args ...any) []any {\n\treturn args\n}\n\nfunc NilIfZero(i int64) any {\n\tif i == 0 {\n\t\treturn nil","sourceCodeStart":231,"sourceCodeEnd":267,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/external/golib/sqlutils/sqlutils.go#L231-L267","documentation":"ExecNoPrepare runs db.Exec without prepared statements, wrapped in a recover guard. If the supplied callback-free execution path panics — typically inside driver code or argument marshaling — the panic is converted into this error. Like QueryRowsMap's recover, it indicates a Go panic happened, not an ordinary SQL error.","triggerScenarios":"Calling sqlutils.ExecNoPrepare where db.Exec or argument conversion panics: nil *sql.DB pointer, driver panic on malformed args, or unsupported value types passed in args.","commonSituations":"Passing a nil db handle into a helper; passing unsupported types (e.g. channels, funcs) as query args; driver bugs with certain value types in no-prepare mode.","solutions":["Inspect the recovered panic value in the message and fix the argument/handle bug at the call site","Verify the *sql.DB passed in is non-nil and properly opened before calling ExecNoPrepare","Ensure all query args are driver-supported scalar types (strings, ints, []byte, time.Time, sql.Null*)"],"exampleFix":"// before\nsqlutils.ExecNoPrepare(db, q, args...)\n// after\nif db == nil {\n    return fmt.Errorf(\"db handle is nil\")\n}\nsqlutils.ExecNoPrepare(db, q, args...)","handlingStrategy":"validation","validationCode":"if db == nil {\n    return fmt.Errorf(\"ExecNoPrepare: nil *sql.DB\")\n}\nfor i, a := range args {\n    switch a.(type) {\n    case nil, string, int, int64, float64, bool, []byte, time.Time:\n    default:\n        return fmt.Errorf(\"ExecNoPrepare: unsupported arg type at %d: %T\", i, a)\n    }\n}","typeGuard":null,"tryCatchPattern":"if _, err := sqlutils.ExecNoPrepare(db, q, args...); err != nil {\n    if strings.Contains(err.Error(), \"unexpected error\") {\n        log.Errorf(\"panic converted to error: %v\", err)\n    }\n    return err\n}","preventionTips":["Validate the db handle is non-nil before helper calls","Only pass driver-supported scalar types as args","Treat 'unexpected error' messages as callback/argument bugs, not SQL failures"],"tags":["panic","sql","recovered-panic"],"backgroundTag":"recovered-panic-in-callback","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}