vitessio/vitess · error · ErrUnauthorized
%w: cannot cleanup schema migration in %s
Error message
%w: cannot cleanup schema migration in %s
What it means
VTAdmin's CleanupSchemaMigration RPC returns this when the caller's role lacks the 'cleanup' action on the SchemaMigration resource for the target cluster. The API rejects the request before contacting any cluster, wrapping errors.ErrUnauthorized. This is a deliberate RBAC denial.
Source
Thrown at go/vt/vtadmin/api.go:549
}
c, err := api.getClusterForRequest(req.ClusterId)
if err != nil {
return nil, err
}
return c.CancelSchemaMigration(ctx, req.Request)
}
// CleanupSchemaMigration is part of the vtadminpb.VTAdminServer interface.
func (api *API) CleanupSchemaMigration(ctx context.Context, req *vtadminpb.CleanupSchemaMigrationRequest) (*vtctldatapb.CleanupSchemaMigrationResponse, error) {
span, ctx := trace.NewSpan(ctx, "API.CleanupSchemaMigration")
defer span.Finish()
span.Annotate("cluster_id", req.ClusterId)
if !api.authz.IsAuthorized(ctx, req.ClusterId, rbac.SchemaMigrationResource, rbac.CleanupSchemaMigrationAction) {
return nil, fmt.Errorf("%w: cannot cleanup schema migration in %s", errors.ErrUnauthorized, req.ClusterId)
}
c, err := api.getClusterForRequest(req.ClusterId)
if err != nil {
return nil, err
}
return c.CleanupSchemaMigration(ctx, req.Request)
}
// CompleteSchemaMigration is part of the vtadminpb.VTAdminServer interface.
func (api *API) CompleteSchemaMigration(ctx context.Context, req *vtadminpb.CompleteSchemaMigrationRequest) (*vtctldatapb.CompleteSchemaMigrationResponse, error) {
span, ctx := trace.NewSpan(ctx, "API.CompleteSchemaMigration")
defer span.Finish()
span.Annotate("cluster_id", req.ClusterId)
if !api.authz.IsAuthorized(ctx, req.ClusterId, rbac.SchemaMigrationResource, rbac.CompleteSchemaMigrationAction) {View on GitHub (pinned to 01a25a7d17)
Solutions
- Grant the 'cleanup' action on the schema-migration resource to the caller's role in the RBAC config
- Check that the cluster ID in the request is covered by the intended role (add wildcard if appropriate)
- Apply the config change and restart vtadmin
Example fix
// before
- resource: schema-migration
actions: [get, create, cancel]
// after
- resource: schema-migration
actions: [get, create, cancel, cleanup] Defensive patterns
Strategy: validation
Validate before calling
const canCleanup = permissions.some(rule => rule.resource === 'schema-migration' && (rule.actions.includes('cleanup') || rule.actions.includes('*')));
if (!canCleanup) throw new Error('missing cleanup permission for schema-migration'); Type guard
function isCleanupDenied(err: unknown): boolean {
return err instanceof Error && err.message.includes('cannot cleanup schema migration');
} Try / catch
try {
await cleanupSchemaMigration(clusterId, uuid);
} catch (err) {
if (String(err).includes('cannot cleanup schema migration')) {
escalateToAdmin('cleanup grant needed for ' + clusterId);
} else {
throw err;
}
} Prevention
- Audit RBAC actions for schema-migration lifecycle ops (create/cancel/complete/cleanup) as a set
- Keep cluster IDs consistent between request and role scope
- Restart vtadmin after RBAC edits
When it happens
Trigger: Calling CleanupSchemaMigration (POST /schema/cleanup) against a cluster whose RBAC rules do not grant the caller the cleanup action.
Common situations: Attempting to clean up a completed/failed migration with a role that only allows read or create; copy-pasted RBAC rules that miss the newer cleanup/complete/cancel actions; cluster-scoped rules that don't match the request's ClusterId.
Related errors
- %w: cannot create schema migration in %s
- %w: cannot cancel schema migration in %s
- %w: cannot complete schema migration in %s
- %w: cannot launch schema migration in %s
- %w: cannot retry schema migration in %s
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/5a8cad776ff4da8e.
Report an issue: GitHub.