vitessio/vitess · error · ErrUnauthorized
%w: cannot create keyspace in %s
Error message
%w: cannot create keyspace in %s
What it means
VTAdmin's CreateKeyspace RPC returns this when the caller is not authorized for the 'create' action on the Keyspace resource in the requested cluster. The check precedes any cluster resolution and wraps errors.ErrUnauthorized. It is an RBAC policy denial at the API layer.
Source
Thrown at go/vt/vtadmin/api.go:608
return nil, err
}
cluster.AnnotateSpan(c, span)
return c.Vtctld.ConcludeTransaction(ctx, &vtctldatapb.ConcludeTransactionRequest{
Dtid: req.Dtid,
})
}
// CreateKeyspace is part of the vtadminpb.VTAdminServer interface.
func (api *API) CreateKeyspace(ctx context.Context, req *vtadminpb.CreateKeyspaceRequest) (*vtadminpb.CreateKeyspaceResponse, error) {
span, ctx := trace.NewSpan(ctx, "API.CreateKeyspace")
defer span.Finish()
span.Annotate("cluster_id", req.ClusterId)
if !api.authz.IsAuthorized(ctx, req.ClusterId, rbac.KeyspaceResource, rbac.CreateAction) {
return nil, fmt.Errorf("%w: cannot create keyspace in %s", errors.ErrUnauthorized, req.ClusterId)
}
c, err := api.getClusterForRequest(req.ClusterId)
if err != nil {
return nil, err
}
ks, err := c.CreateKeyspace(ctx, req.Options)
if err != nil {
return nil, err
}
return &vtadminpb.CreateKeyspaceResponse{
Keyspace: ks,
}, nil
}
// CreateShard is part of the vtadminpb.VTAdminServer interface.View on GitHub (pinned to 01a25a7d17)
Solutions
- Add action 'create' to the keyspace resource rules for the caller's role in the vtadmin RBAC config
- Ensure the role is scoped to the correct cluster ID or uses a wildcard
- Restart vtadmin and re-authenticate
Example fix
// before
- resource: keyspace
actions: [get]
// after
- resource: keyspace
actions: [get, create, delete] Defensive patterns
Strategy: validation
Validate before calling
const canCreateKeyspace = permissions.some(rule => rule.resource === 'keyspace' && (rule.actions.includes('create') || rule.actions.includes('*')) && (rule.clusters.includes(clusterId) || rule.clusters.includes('*')));
if (!canCreateKeyspace) throw new Error('RBAC denies keyspace create in ' + clusterId); Type guard
function isKeyspaceCreateDenied(err: unknown): boolean {
return err instanceof Error && err.message.includes('cannot create keyspace');
} Try / catch
try {
await createKeyspace(clusterId, keyspaceReq);
} catch (err) {
if (String(err).includes('cannot create keyspace')) {
promptForElevatedRole();
} else {
throw err;
}
} Prevention
- Use dedicated provisioning roles with keyspace create/delete for automation
- Validate cluster ID against the role's scope before calling
- Keep rbac config in version control and review action lists
When it happens
Trigger: Calling CreateKeyspace (POST /keyspace) where the caller's RBAC role for req.ClusterId lacks keyspace create permission.
Common situations: CI/service accounts with read-only roles attempting keyspace provisioning; RBAC config that only whitelists 'get' on keyspaces; typos in role resource names causing default-deny.
Related errors
- %w: cannot delete keyspace in %s
- %w: cannot create schema migration in %s
- %w: cannot cancel schema migration in %s
- %w: cannot cleanup schema migration in %s
- %w: cannot complete schema migration in %s
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/2c6fe0755fcb079e.
Report an issue: GitHub.