{"record":{"id":"9afb4c37ff457cd3","repo":"golang-migrate/migrate","slug":"both-password-and-usemsi-true-were-passed","errorCode":null,"errorMessage":"both password and useMsi=true were passed","messagePattern":"both password and useMsi=true were passed","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"database/sqlserver/sqlserver.go","lineNumber":32,"sourceCode":"\t\"github.com/Azure/go-autorest/autorest/adal\"\n\t\"github.com/golang-migrate/migrate/v4\"\n\t\"github.com/golang-migrate/migrate/v4/database\"\n\tmssql \"github.com/microsoft/go-mssqldb\" // mssql support\n)\n\nfunc init() {\n\tdatabase.Register(\"sqlserver\", &SQLServer{})\n}\n\n// DefaultMigrationsTable is the name of the migrations table in the database\nvar DefaultMigrationsTable = \"schema_migrations\"\n\nvar (\n\tErrNilConfig                 = fmt.Errorf(\"no config\")\n\tErrNoDatabaseName            = fmt.Errorf(\"no database name\")\n\tErrNoSchema                  = fmt.Errorf(\"no schema\")\n\tErrDatabaseDirty             = fmt.Errorf(\"database is dirty\")\n\tErrMultipleAuthOptionsPassed = fmt.Errorf(\"both password and useMsi=true were passed\")\n)\n\nvar lockErrorMap = map[int]string{\n\t-1:   \"The lock request timed out.\",\n\t-2:   \"The lock request was canceled.\",\n\t-3:   \"The lock request was chosen as a deadlock victim.\",\n\t-999: \"Parameter validation or other call error.\",\n}\n\n// Config for database\ntype Config struct {\n\tMigrationsTable string\n\tDatabaseName    string\n\tSchemaName      string\n}\n\n// SQL Server connection\ntype SQLServer struct {","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/golang-migrate/migrate/blob/01a9643f1475e75bb6d6224ddeaf9d8e2434ca8a/database/sqlserver/sqlserver.go#L14-L50","documentation":"ErrMultipleAuthOptionsPassed is returned by the sqlserver driver's Open when the URL both enables useMsi=true and contains a password in the userinfo. Azure MSI and explicit password auth are mutually exclusive, so the driver rejects the combination.","triggerScenarios":"Opening sqlserver://user:password@host/db?useMsi=true — the URL userinfo carries a password while MSI is requested.","commonSituations":"Templated connection strings where a default password is always injected; switching local dev (password) to Azure (MSI) without stripping the password; copy-pasted URLs accumulating parameters.","solutions":["Remove the password (and typically username) from the URL userinfo when useMsi=true is set","Use the same connection-string template with a conditional that omits credentials for MSI environments","If password auth is intended, drop useMsi=true from the query"],"exampleFix":"// before\nmigrate.Open(\"sqlserver://user:pass@myserver.database.windows.net:1433?database=mydb&useMsi=true\")\n// after\nmigrate.Open(\"sqlserver://myserver.database.windows.net:1433?database=mydb&useMsi=true\")","handlingStrategy":"validation","validationCode":"u, _ := url.Parse(dsn)\n_, hasPass := u.User.Password()\nif hasPass && u.Query().Get(\"useMsi\") == \"true\" {\n    return errors.New(\"cannot combine URL password with useMsi=true\")\n}","typeGuard":"func authOptionsConsistent(u *url.URL) bool {\n    _, hasPass := u.User.Password()\n    return !(hasPass && u.Query().Get(\"useMsi\") == \"true\")\n}","tryCatchPattern":null,"preventionTips":["Templatize DSNs so MSI environments omit the password segment entirely","Separate dev (password) and Azure (MSI) DSN templates","Validate DSNs at config load, before reaching migrate.Open"],"tags":["go","sqlserver","database","migration","azure","authentication"],"backgroundTag":"conflicting-auth-options","analyzedSha":"01a9643f1475e75bb6d6224ddeaf9d8e2434ca8a","analyzedAt":"2026-09-02T19:38:29.671Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-10T02:17:09.455Z"}