{"record":{"id":"c00b0a8a2953a361","repo":"iflytek/astron-agent","slug":"mysql-client-is-nil","errorCode":null,"errorMessage":"mysql client is nil","messagePattern":"mysql client is nil","errorType":"console","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"core/tenant/tools/database/migrations.go","lineNumber":32,"sourceCode":")\n\ntype migration struct {\n\tVersion     string\n\tDescription string\n\tStatements  []string\n}\n\nvar migrations = []migration{\n\t{\n\t\tVersion:     initVersion,\n\t\tDescription: \"init tenant tables and seed data\",\n\t\tStatements:  tenantInitStatements,\n\t},\n}\n\nfunc runMigrations(client *sql.DB) error {\n\tif client == nil {\n\t\treturn errors.New(\"mysql client is nil\")\n\t}\n\n\tif err := ensureMigrationTable(client); err != nil {\n\t\treturn err\n\t}\n\n\tunlock, err := acquireMigrationLock(client)\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer unlock()\n\n\tif err := stampLegacyDatabase(client); err != nil {\n\t\treturn err\n\t}\n\n\tappliedVersions, err := loadAppliedVersions(client)\n\tif err != nil {","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/iflytek/astron-agent/blob/5e758547a83371a5a4b29dadf4ac03e8dd527635/core/tenant/tools/database/migrations.go#L14-L50","documentation":"runMigrations is the entry point for applying tenantInitStatements via a schema-migrations table. It throws 'mysql client is nil' when the *sql.DB handed to it is nil, meaning MySQL initialization failed earlier (or buildMysql returned a nil client) but execution continued into migrations.","triggerScenarios":"initializeMysqlClient calls runMigrations(db) where db is a nil *sql.DB — happens when buildMysql returned nil after an error that was swallowed, or initializeMysqlClient is invoked before MySQL configuration is available.","commonSituations":"MySQL init failed (bad DSN, unreachable server) but the error was logged-not-propagated; wiring change in server startup passed the zero-value Database; tests calling runMigrations(nil).","solutions":["Fix the upstream buildMysql/initializeMysqlClient error path so a failed MySQL build aborts startup instead of proceeding with nil.","Check startup logs for the earlier MySQL error (empty url, bad DSN, connection refused) that produced the nil client.","Ensure buildMysql returns (nil, err) and initializeMysqlClient checks err before calling runMigrations.","Add an integration test that MySQL failure causes a fast, explicit startup failure."],"exampleFix":"// before\nclient, err := buildMysql(conf)\nif err != nil {\n    log.Printf(\"mysql init failed: %v\", err)\n}\nreturn runMigrations(client)\n\n// after\nclient, err := buildMysql(conf)\nif err != nil {\n    return fmt.Errorf(\"build mysql client: %w\", err)\n}\nreturn runMigrations(client)","handlingStrategy":"type-guard","validationCode":"if client == nil {\n\treturn errors.New(\"mysql client not initialized; aborting before migrations\")\n}","typeGuard":"func readyForMigrations(db *sql.DB) bool { return db != nil }","tryCatchPattern":"if err := initializeMysqlClient(cfg); err != nil {\n\tlog.Fatalf(\"mysql init failed: %v\", err)\n}","preventionTips":["Propagate, don't swallow, errors from buildMysql so nil clients never reach migrations.","Make startup fail fast: any infrastructure init error should abort the process.","Add an integration test that simulates MySQL unavailability and asserts startup failure."],"tags":["mysql","null-pointer","migrations","go"],"backgroundTag":"internal-invariant-violation","analyzedSha":"5e758547a83371a5a4b29dadf4ac03e8dd527635","analyzedAt":"2026-09-12T08:03:51.356Z","contentChangedAt":"2026-09-12T08:03:51.356Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}