{"record":{"id":"e417ae274ca2865a","repo":"vitessio/vitess","slug":"w-cannot-launch-schema-migration-in-s","errorCode":null,"errorMessage":"%w: cannot launch schema migration in %s","messagePattern":"%w: cannot launch schema migration in (.+?)","errorType":"validation","errorClass":"ErrUnauthorized","httpStatus":null,"severity":"error","filePath":"go/vt/vtadmin/api.go","lineNumber":2014,"sourceCode":"\n\tif rec.HasErrors() {\n\t\treturn nil, rec.Error()\n\t}\n\n\treturn &vtadminpb.GetWorkflowsResponse{\n\t\tWorkflowsByCluster: results,\n\t}, nil\n}\n\n// LaunchSchemaMigration is part of the vtadminpb.VTAdminServer interface.\nfunc (api *API) LaunchSchemaMigration(ctx context.Context, req *vtadminpb.LaunchSchemaMigrationRequest) (*vtctldatapb.LaunchSchemaMigrationResponse, error) {\n\tspan, ctx := trace.NewSpan(ctx, \"API.LaunchSchemaMigration\")\n\tdefer span.Finish()\n\n\tspan.Annotate(\"cluster_id\", req.ClusterId)\n\n\tif !api.authz.IsAuthorized(ctx, req.ClusterId, rbac.SchemaMigrationResource, rbac.LaunchSchemaMigrationAction) {\n\t\treturn nil, fmt.Errorf(\"%w: cannot launch schema migration in %s\", errors.ErrUnauthorized, req.ClusterId)\n\t}\n\n\tc, err := api.getClusterForRequest(req.ClusterId)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn c.LaunchSchemaMigration(ctx, req.Request)\n}\n\n// MaterializeCreate is part of the vtadminpb.VTAdminServer interface.\nfunc (api *API) MaterializeCreate(ctx context.Context, req *vtadminpb.MaterializeCreateRequest) (*vtctldatapb.MaterializeCreateResponse, error) {\n\tspan, ctx := trace.NewSpan(ctx, \"API.MaterializeCreate\")\n\tdefer span.Finish()\n\n\tspan.Annotate(\"cluster_id\", req.ClusterId)\n\n\tif !api.authz.IsAuthorized(ctx, req.ClusterId, rbac.WorkflowResource, rbac.CreateAction) {","sourceCodeStart":1996,"sourceCodeEnd":2032,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtadmin/api.go#L1996-L2032","documentation":"API.LaunchSchemaMigration enforces RBAC before doing any work: if the caller's credentials are not authorized for the LaunchSchemaMigration action on the SchemaMigrationResource in the requested cluster, it returns errors.ErrUnauthorized wrapped with this message. It is a sentinel-wrapped error, testable with errors.Is, and thrown before any cluster lookup or vtctld call.","triggerScenarios":"Calling LaunchSchemaMigration with credentials (from the vtadmin auth context — e.g. missing/invalid bearer token, or identity not matching an RBAC rule) that lack permission for schema-migration launch in req.ClusterId.","commonSituations":"User authenticated but their role's RBAC policy lacks launch_schema_migration; cluster-scoped rule that doesn't cover this cluster ID; authz config file not reloaded after adding permissions; missing auth headers from an API client.","solutions":["Check the RBAC config (authz rules) for a rule granting rbac.LaunchSchemaMigrationAction on SchemaMigrationResource for the caller's identity in this cluster","Verify the client is sending valid credentials/headers recognized by vtadmin's auth middleware","Fix cluster ID in the request if the rule is cluster-scoped and the ID mismatches","Reload/restart vtadmin after editing the authorization config"],"exampleFix":"// rbac.yaml before: read-only user\nrules:\n  - resource: \"SchemaMigration\"\n    actions: [\"get\"]\n// after: grant launch action\nrules:\n  - resource: \"SchemaMigration\"\n    actions: [\"get\", \"launch\", \"cancel\", \"cleanup\", \"complete\"]","handlingStrategy":"validation","validationCode":"// Go: pre-check authorization client-side\nif !userRoles.Can(\"launch\", \"SchemaMigration\", clusterID) {\n\treturn fmt.Errorf(\"user lacks launch schema migration permission in %s\", clusterID)\n}","typeGuard":"func isUnauthorized(err error) bool {\n\treturn errors.Is(err, vtadminerrors.ErrUnauthorized)\n}","tryCatchPattern":"resp, err := client.LaunchSchemaMigration(ctx, req)\nif err != nil {\n\tif isUnauthorized(err) {\n\t\t// surface permission-denied UI, don't retry\n\t}\n\treturn err\n}","preventionTips":["Grant SchemaMigration launch action to operator roles in RBAC config","Send auth credentials/headers on every vtadmin request","Test RBAC rules with a least-privilege user before rollout","Keep cluster-scoped rules aligned with actual cluster IDs"],"tags":["vtadmin","rbac","authorization","schema-migration"],"backgroundTag":"rbac-unauthorized","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}