{"record":{"id":"11a840a348982db5","repo":"bytebase/bytebase","slug":"failed-to-query-grants-for-s","errorCode":null,"errorMessage":"failed to query grants for %s","messagePattern":"failed to query grants for (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"backend/plugin/db/mysql/role.go","lineNumber":54,"sourceCode":"\t\t\tcontinue\n\t\t}\n\t\tattribute := strings.Join(grantList, \"\\n\")\n\t\tinstanceRoles = append(instanceRoles, &storepb.InstanceRole{\n\t\t\tName:      name,\n\t\t\tAttribute: &attribute,\n\t\t})\n\t}\n\treturn instanceRoles\n}\n\n// getGrantFromUser reads grants for user with format \"'<user>'@'<host>'\".\nfunc (d *Driver) getGrantFromUser(ctx context.Context, name string) ([]string, error) {\n\tgrantQuery := fmt.Sprintf(\"SHOW GRANTS FOR %s\", name)\n\tgrantRows, err := d.db.QueryContext(ctx,\n\t\tgrantQuery,\n\t)\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"failed to query grants for %s\", name)\n\t}\n\tdefer grantRows.Close()\n\n\tgrants := []string{}\n\tfor grantRows.Next() {\n\t\tvar grant string\n\t\tif err := grantRows.Scan(&grant); err != nil {\n\t\t\treturn nil, errors.Wrapf(err, \"failed to scan grants for %s\", name)\n\t\t}\n\t\tgrants = append(grants, grant)\n\t}\n\tif err := grantRows.Err(); err != nil {\n\t\treturn nil, errors.Wrapf(err, \"failed to iterate grants for %s\", name)\n\t}\n\treturn grants, nil\n}\n\n// getUsersFromUserAttributes reads users from information_schema.user_attributes, returns the list of users with format \"'<user>'@'<host>'\".","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/bytebase/bytebase/blob/1870550677fe08f0d2a78c07acd27541464eb945/backend/plugin/db/mysql/role.go#L36-L72","documentation":"getGrantFromUser runs 'SHOW GRANTS FOR <user>' to enumerate a MySQL account's grants. If the query fails — most commonly because the user@host does not exist, or the connected account lacks SELECT on the mysql system tables — the error is wrapped as 'failed to query grants for %s'.","triggerScenarios":"getInstanceRoles calls getGrantFromUser for each role/user name returned by the server; SHOW GRANTS FOR fails for a deleted-or-renamed account, a malformed user identifier, or when the connection lacks privileges to view that account's grants.","commonSituations":"Stale role entries after users were dropped; connecting with an account missing mysql.* read privileges; user names containing special characters that need quoting; replication/monitoring accounts with limited visibility.","solutions":["Verify the user@host exists: run SELECT User, Host FROM mysql.user WHERE User='...'","Connect with an account that has privileges to see grants for all users (e.g. WITH GRANT OPTION or SELECT on mysql.*)","Quote the user identifier properly ('user'@'host') to handle special characters","Skip or log-and-continue for users that no longer exist instead of failing the whole role sync"],"exampleFix":"// before\ngrantQuery := fmt.Sprintf(\"SHOW GRANTS FOR %s\", name)\n// after\ngrantQuery := fmt.Sprintf(\"SHOW GRANTS FOR %s\", quoteMySQLUserHost(name)) // handles 'user'@'host' quoting\nif err != nil {\n  if isUserNotExistErr(err) { continue } // skip stale accounts\n  return nil, errors.Wrapf(err, \"failed to query grants for %s\", name)\n}","handlingStrategy":"try-catch","validationCode":"// before syncing roles, verify visibility\n// SELECT COUNT(*) FROM mysql.user WHERE User = ?  -> account exists and is visible","typeGuard":null,"tryCatchPattern":"grants, err := d.getGrantFromUser(ctx, name)\nif err != nil {\n  if strings.Contains(err.Error(), \"failed to query grants for\") {\n    log.Warn(\"skipping grants for account\", \"user\", name, \"err\", err) // or check underlying MySQL error 1141\n    continue\n  }\n  return err\n}","preventionTips":["Connect with an account having SELECT on mysql.* or SHOW GRANTS visibility","Quote identifiers as 'user'@'host'","Purge or ignore stale users after drops/renames","Check account existence before SHOW GRANTS FOR"],"tags":["mysql","grants","privileges","query"],"backgroundTag":"sql-query-failed","analyzedSha":"1870550677fe08f0d2a78c07acd27541464eb945","analyzedAt":"2026-09-06T21:16:13.665Z","contentChangedAt":"2026-09-06T21:16:13.665Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}