vitessio/vitess · error · ErrUnauthorized
%w: cannot cancel schema migration in %s
Error message
%w: cannot cancel schema migration in %s
What it means
VTAdmin's CancelSchemaMigration RPC returns this when the caller is not authorized with the 'cancel' action on the SchemaMigration resource for the given cluster. The check runs before any cluster lookup, wrapping errors.ErrUnauthorized. It indicates RBAC policy denial, not a migration failure.
Source
Thrown at go/vt/vtadmin/api.go:530
if req.CallerId != "" {
req.Request.CallerId = &vtrpcpb.CallerID{Principal: req.CallerId}
}
// Set the default wait replicas timeout.
req.Request.WaitReplicasTimeout = protoutil.DurationToProto(grpcvtctldserver.DefaultWaitReplicasTimeout)
return c.ApplySchema(ctx, req.Request)
}
// CancelSchemaMigration is part of the vtadminpb.VTAdminServer interface.
func (api *API) CancelSchemaMigration(ctx context.Context, req *vtadminpb.CancelSchemaMigrationRequest) (*vtctldatapb.CancelSchemaMigrationResponse, error) {
span, ctx := trace.NewSpan(ctx, "API.CancelSchemaMigration")
defer span.Finish()
span.Annotate("cluster_id", req.ClusterId)
if !api.authz.IsAuthorized(ctx, req.ClusterId, rbac.SchemaMigrationResource, rbac.CancelAction) {
return nil, fmt.Errorf("%w: cannot cancel schema migration in %s", errors.ErrUnauthorized, req.ClusterId)
}
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) {View on GitHub (pinned to 01a25a7d17)
Solutions
- Add action 'cancel' (or use a wildcard) to the caller's role for the schema-migration resource in the RBAC config
- Confirm the request's cluster ID is the one the permissive role covers
- Reload/restart vtadmin with the updated RBAC config
Example fix
// before
- resource: schema-migration
actions: [get, create]
// after
- resource: schema-migration
actions: [get, create, cancel, complete, cleanup] Defensive patterns
Strategy: validation
Validate before calling
const canCancel = permissions.some(rule => rule.resource === 'schema-migration' && (rule.actions.includes('cancel') || rule.actions.includes('*')) && (rule.clusters.includes(clusterId) || rule.clusters.includes('*')));
if (!canCancel) console.warn('RBAC will deny CancelSchemaMigration for cluster ' + clusterId); Type guard
function isCancelUnauthorized(err: unknown): boolean {
return err instanceof Error && err.message.includes('cannot cancel schema migration');
} Try / catch
try {
await cancelSchemaMigration(clusterId, uuid);
} catch (err) {
if (String(err).includes('cannot cancel schema migration')) {
requestRbacGrant(['cancel']);
} else {
throw err;
}
} Prevention
- Include cancel/complete/cleanup alongside create when granting schema-migration permissions
- Verify per-cluster role scoping in rbac config
- Test permission changes in a staging cluster first
When it happens
Trigger: Calling CancelSchemaMigration (DELETE /schema/cancel) for a cluster where the caller's role omits the cancel action on schema-migration resources.
Common situations: Operators with create-only schema permissions trying to cancel an in-flight migration; RBAC config that enumerates actions narrowly (get, create) but not cancel; wrong cluster ID mapped to a restrictive role.
Related errors
- %w: cannot create schema migration in %s
- %w: cannot cleanup 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/caa77c34e9eb1f69.
Report an issue: GitHub.