{"record":{"id":"75e8a98ac3cbcb33","repo":"vitessio/vitess","slug":"w-cannot-create-workflow-in-s","errorCode":null,"errorMessage":"%w: cannot create workflow in %s","messagePattern":"%w: cannot create workflow in (.+?)","errorType":"validation","errorClass":"ErrUnauthorized","httpStatus":null,"severity":"error","filePath":"go/vt/vtadmin/api.go","lineNumber":2033,"sourceCode":"\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) {\n\t\treturn nil, fmt.Errorf(\"%w: cannot create workflow 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\t// Parser with default options. New() itself initializes with default MySQL version.\n\tparser, err := sqlparser.New(sqlparser.Options{\n\t\tTruncateUILen:  512,\n\t\tTruncateErrLen: 0,\n\t})\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treq.Request.Settings.TableSettings, err = vreplcommon.ParseTableMaterializeSettings(req.TableSettings, parser)\n\tif err != nil {\n\t\treturn nil, err","sourceCodeStart":2015,"sourceCodeEnd":2051,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtadmin/api.go#L2015-L2051","documentation":"API.MaterializeCreate checks RBAC before creating a materialize workflow: callers not authorized for the Create action on WorkflowResource in req.ClusterId get errors.ErrUnauthorized wrapped with this message. The check happens before cluster resolution and any vtctld interaction, so authorization failure always yields this specific error.","triggerScenarios":"Calling MaterializeCreate (materialization workflow creation) with credentials whose RBAC rules do not grant workflow create in the target cluster — missing role mapping, cluster-scoped rule excluding this cluster, or unauthenticated request.","commonSituations":"Operator accounts with read-only RBAC attempting workflow creation; new cluster added without extending workflow RBAC rules; token/headers stripped by a reverse proxy; authz YAML typo in action names.","solutions":["Add/grant the Create action on the Workflow resource for the caller's role in the RBAC configuration","Confirm the client sends the identity headers/token vtadmin expects","Check the cluster ID matches the cluster-scoped RBAC rule","Validate the authz config (action names, cluster patterns) and restart vtadmin"],"exampleFix":"// rbac.yaml before\n- resource: \"Workflow\"\n  actions: [\"get\"]\n// after\n- resource: \"Workflow\"\n  actions: [\"get\", \"create\"]","handlingStrategy":"validation","validationCode":"// pre-check workflow create permission\nif !userRoles.Can(\"create\", \"Workflow\", req.ClusterId) {\n\treturn fmt.Errorf(\"user cannot create workflows in %s\", req.ClusterId)\n}","typeGuard":"func isUnauthorized(err error) bool {\n\treturn errors.Is(err, vtadminerrors.ErrUnauthorized)\n}","tryCatchPattern":"resp, err := client.MaterializeCreate(ctx, req)\nif err != nil {\n\tif isUnauthorized(err) {\n\t\t// prompt for elevated role / correct cluster; no retry\n\t}\n\treturn err\n}","preventionTips":["Grant Workflow create action to roles that need materializations","Verify proxies don't strip vtadmin auth headers","Audit RBAC YAML for action-name typos","Reload authz config after edits (restart vtadmin)"],"tags":["vtadmin","rbac","authorization","workflow"],"backgroundTag":"rbac-unauthorized","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}