{"record":{"id":"086ab5aca05c9da2","repo":"flipped-aurora/gin-vue-admin","slug":"db-type-mismatch","errorCode":null,"errorMessage":"db type mismatch","messagePattern":"db type mismatch","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/service/system/sys_initdb.go","lineNumber":42,"sourceCode":"\tPgsql           = \"pgsql\"\n\tSqlite          = \"sqlite\"\n\tMssql           = \"mssql\"\n\tInitSuccess     = \"\\n[%v] --> 初始数据成功!\\n\"\n\tInitDataExist   = \"\\n[%v] --> %v 的初始数据已存在!\\n\"\n\tInitDataFailed  = \"\\n[%v] --> %v 初始数据失败! \\nerr: %+v\\n\"\n\tInitDataSuccess = \"\\n[%v] --> %v 初始数据成功!\\n\"\n)\n\nconst (\n\tInitOrderSystem   = 10\n\tInitOrderInternal = 1000\n\tInitOrderExternal = 100000\n)\n\nvar (\n\tErrMissingDBContext        = errors.New(\"missing db in context\")\n\tErrMissingDependentContext = errors.New(\"missing dependent value in context\")\n\tErrDBTypeMismatch          = errors.New(\"db type mismatch\")\n)\n\n// SubInitializer 提供 source/*/init() 使用的接口，每个 initializer 完成一个初始化过程\ntype SubInitializer interface {\n\tInitializerName() string // 不一定代表单独一个表，所以改成了更宽泛的语义\n\tMigrateTable(ctx context.Context) (next context.Context, err error)\n\tInitializeData(ctx context.Context) (next context.Context, err error)\n\tTableCreated(ctx context.Context) bool\n\tDataInserted(ctx context.Context) bool\n}\n\n// TypedDBInitHandler 执行传入的 initializer\ntype TypedDBInitHandler interface {\n\tEnsureDB(ctx context.Context, conf *request.InitDB) (context.Context, error) // 建库，失败属于 fatal error，因此让它 panic\n\tWriteConfig(ctx context.Context) error                                       // 回写配置\n\tInitTables(ctx context.Context, inits initSlice) error                       // 建表 handler\n\tInitData(ctx context.Context, inits initSlice) error                         // 建数据 handler\n}","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/flipped-aurora/gin-vue-admin/blob/3136500ef380842b0eb6c4daa87c3f8a47fcf9e0/server/service/system/sys_initdb.go#L24-L60","documentation":"ErrDBTypeMismatch is a sentinel error in the init-db service of gin-vue-admin. Each DB-specific InitHandler's EnsureDB double-checks that the ctx value \"dbtype\" matches the handler's own database type; if it does not (or is absent), the handler refuses to run and returns this error. It is an internal consistency guard: the handler chosen in InitDB and the dbtype stamped into the context must agree.","triggerScenarios":"Calling a DB-specific EnsureDB handler directly (e.g. MysqlInitHandler.EnsureDB) with a context that has no \"dbtype\" string value, or one stamped with a different type (e.g. ctx with dbtype=\"pgsql\" passed to the mssql handler). Not reachable via the normal InitDB entry point, which always sets dbtype consistently from conf.DBType.","commonSituations":"Custom initializer code or plugins that construct their own context and call a specific handler; refactoring where conf.DBType mapping (sys_initdb.go:109-125) was changed or bypassed; tests invoking handlers in isolation without stamping dbtype.","solutions":["When calling a handler's EnsureDB directly, stamp the context first: ctx = context.WithValue(ctx, \"dbtype\", \"mysql\") matching the handler.","Prefer going through InitDBService.InitDB(conf), which picks the handler and sets dbtype from conf.DBType automatically.","Ensure conf.DBType is one of mysql/pgsql/sqlite/mssql so the switch maps to the intended handler.","If you wrote custom dispatch code, keep the dbtype string value in sync with the handler you instantiate."],"exampleFix":"// before\nctx := context.WithValue(context.TODO(), \"dbtype\", \"pgsql\")\nctx, err = mysqlHandler.EnsureDB(ctx, &conf) // -> ErrDBTypeMismatch\n// after\nctx := context.WithValue(context.TODO(), \"dbtype\", \"mysql\")\nctx, err = mysqlHandler.EnsureDB(ctx, &conf)","handlingStrategy":"validation","validationCode":"func dbTypeStamped(ctx context.Context) (string, bool) {\n\ts, ok := ctx.Value(\"dbtype\").(string)\n\treturn s, ok\n}\n// before calling EnsureDB: if dbTypeStamped(ctx) != \"mysql\" { stamp it }","typeGuard":"func isDBType(ctx context.Context, want string) bool {\n\ts, ok := ctx.Value(\"dbtype\").(string)\n\treturn ok && s == want\n}","tryCatchPattern":"ctx, err := handler.EnsureDB(ctx, &conf)\nif err != nil {\n\tif errors.Is(err, system.ErrDBTypeMismatch) {\n\t\t// handler/dbtype pair mismatched; route through InitDBService.InitDB instead\n\t}\n\treturn err\n}","preventionTips":["Always let InitDBService.InitDB choose the handler and stamp dbtype.","Never call DB-specific EnsureDB/WriteConfig handlers with hand-built contexts.","Keep the \"dbtype\" context value identical to the handler's DB type.","Test custom initializer pipelines through the full InitDB flow."],"tags":["go","database","initialization"],"backgroundTag":"db-type-mismatch","analyzedSha":"3136500ef380842b0eb6c4daa87c3f8a47fcf9e0","analyzedAt":"2026-08-31T13:50:02.721Z","schemaVersion":2},"datasetVersion":"2026-08-31T22:30:34.772Z"}