bytebase/bytebase · warning

failed to query grants for %s

Error message

failed to query grants for %s

What it means

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'.

Source

Thrown at backend/plugin/db/mysql/role.go:54

			continue
		}
		attribute := strings.Join(grantList, "\n")
		instanceRoles = append(instanceRoles, &storepb.InstanceRole{
			Name:      name,
			Attribute: &attribute,
		})
	}
	return instanceRoles
}

// getGrantFromUser reads grants for user with format "'<user>'@'<host>'".
func (d *Driver) getGrantFromUser(ctx context.Context, name string) ([]string, error) {
	grantQuery := fmt.Sprintf("SHOW GRANTS FOR %s", name)
	grantRows, err := d.db.QueryContext(ctx,
		grantQuery,
	)
	if err != nil {
		return nil, errors.Wrapf(err, "failed to query grants for %s", name)
	}
	defer grantRows.Close()

	grants := []string{}
	for grantRows.Next() {
		var grant string
		if err := grantRows.Scan(&grant); err != nil {
			return nil, errors.Wrapf(err, "failed to scan grants for %s", name)
		}
		grants = append(grants, grant)
	}
	if err := grantRows.Err(); err != nil {
		return nil, errors.Wrapf(err, "failed to iterate grants for %s", name)
	}
	return grants, nil
}

// getUsersFromUserAttributes reads users from information_schema.user_attributes, returns the list of users with format "'<user>'@'<host>'".

View on GitHub (pinned to 1870550677)

Solutions

  1. Verify the user@host exists: run SELECT User, Host FROM mysql.user WHERE User='...'
  2. Connect with an account that has privileges to see grants for all users (e.g. WITH GRANT OPTION or SELECT on mysql.*)
  3. Quote the user identifier properly ('user'@'host') to handle special characters
  4. Skip or log-and-continue for users that no longer exist instead of failing the whole role sync

Example fix

// before
grantQuery := fmt.Sprintf("SHOW GRANTS FOR %s", name)
// after
grantQuery := fmt.Sprintf("SHOW GRANTS FOR %s", quoteMySQLUserHost(name)) // handles 'user'@'host' quoting
if err != nil {
  if isUserNotExistErr(err) { continue } // skip stale accounts
  return nil, errors.Wrapf(err, "failed to query grants for %s", name)
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before syncing roles, verify visibility
// SELECT COUNT(*) FROM mysql.user WHERE User = ?  -> account exists and is visible

Try / catch

grants, err := d.getGrantFromUser(ctx, name)
if err != nil {
  if strings.Contains(err.Error(), "failed to query grants for") {
    log.Warn("skipping grants for account", "user", name, "err", err) // or check underlying MySQL error 1141
    continue
  }
  return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.

Related errors


AI-assisted analysis of bytebase/bytebase@1870550677 (2026-09-06). Data as JSON: /api/errors/11a840a348982db5. Report an issue: GitHub.