vitessio/vitess · warning

%v has an extra %v %v

Error message

%v has an extra %v %v

What it means

diffPermissions compares two Permission sets (left vs right) by sorted primary key. When the left side contains a permission entry (a user or a table in a permission record) that the right side lacks, this error records a drift on the left (leftName).

Source

Thrown at go/vt/mysqlctl/tmutils/permissions.go:178

	return result
}

// PermissionsString pretty-prints Permissions
func PermissionsString(permissions *tabletmanagerdatapb.Permissions) string {
	return printPermissions("User", userPermissionList(permissions.UserPermissions)) +
		printPermissions("Db", dbPermissionList(permissions.DbPermissions))
}

func diffPermissions(name, leftName string, left permissionList, rightName string, right permissionList, er concurrency.ErrorRecorder) {
	leftIndex := 0
	rightIndex := 0
	for leftIndex < left.Len() && rightIndex < right.Len() {
		lpk, lval := left.Get(leftIndex)
		rpk, rval := right.Get(rightIndex)

		// extra value on the left side
		if lpk < rpk {
			er.RecordError(fmt.Errorf("%v has an extra %v %v", leftName, name, lpk))
			leftIndex++
			continue
		}

		// extra value on the right side
		if lpk > rpk {
			er.RecordError(fmt.Errorf("%v has an extra %v %v", rightName, name, rpk))
			rightIndex++
			continue
		}

		// same name, let's see content
		if lval != rval {
			er.RecordError(fmt.Errorf("permissions differ on %v %v:\n%s: %v\n differs from:\n%s: %v", name, lpk, leftName, lval, rightName, rval))
		}
		leftIndex++
		rightIndex++
	}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Diff the permission lists on both sides and apply the missing/extra GRANT/REVOKE so both match
  2. Re-sync permissions from the source of truth (topo or target tablet)
  3. Check for manual GRANT statements run on only one MySQL instance
  4. Re-run DiffPermissions to confirm drift is resolved

Example fix

// before: manual GRANT on left tablet only
// after: apply the same GRANT on both, or REVOKE on left
// REVOKE ... ON db.* FROM 'user'@'host';
Defensive patterns

Strategy: validation

Validate before calling

// compare permission key sets before invoking diff
leftKeys, rightKeys := keySet(left), keySet(right)
for k := range leftKeys {
    if !rightKeys[k] {
        log.Warnf("left has extra permission %v; will be flagged", k)
    }
}

Try / catch

er := tmutils.DiffPermissions("local", permsLocal, "topo", permsTopo)
if er.HasErrors() {
    for _, err := range er.Errors {
        log.Warn("permission drift detected", slog.Any("error", err))
    }
}

Prevention

When it happens

Trigger: Running DiffPermissions (tablet-manager permission sync/checks) when the left source (e.g. local mysqld) has an extra user/DB/table permission entry absent from the right (e.g. expected topo copy).

Common situations: A GRANT was applied directly on one tablet but not replicated to the other; permissions drift after manual dbadmin operations; comparing freshly-restored tablets against topo records.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/6471c3139b5ad266. Report an issue: GitHub.