vitessio/vitess · error · ErrUnauthorized
%w: cannot create shard in %s
Error message
%w: cannot create shard in %s
What it means
VTAdmin's CreateShard RPC returns this when RBAC denies the caller the 'create' action on the Shard resource for the requested cluster. The API enforces the check before resolving the cluster and wraps errors.ErrUnauthorized. It signals a permissions problem, not a shard conflict.
Source
Thrown at go/vt/vtadmin/api.go:634
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.
func (api *API) CreateShard(ctx context.Context, req *vtadminpb.CreateShardRequest) (*vtctldatapb.CreateShardResponse, error) {
span, ctx := trace.NewSpan(ctx, "API.CreateShard")
defer span.Finish()
span.Annotate("cluster_id", req.ClusterId)
if !api.authz.IsAuthorized(ctx, req.ClusterId, rbac.ShardResource, rbac.CreateAction) {
return nil, fmt.Errorf("%w: cannot create shard in %s", errors.ErrUnauthorized, req.ClusterId)
}
c, err := api.getClusterForRequest(req.ClusterId)
if err != nil {
return nil, err
}
return c.CreateShard(ctx, req.Options)
}
// DeleteKeyspace is part of the vtadminpb.VTAdminServer interface.
func (api *API) DeleteKeyspace(ctx context.Context, req *vtadminpb.DeleteKeyspaceRequest) (*vtctldatapb.DeleteKeyspaceResponse, error) {
span, ctx := trace.NewSpan(ctx, "API.DeleteKeyspace")
defer span.Finish()
span.Annotate("cluster_id", req.ClusterId)
if !api.authz.IsAuthorized(ctx, req.ClusterId, rbac.KeyspaceResource, rbac.DeleteAction) {View on GitHub (pinned to 01a25a7d17)
Solutions
- Add action 'create' to the shard resource rules for the caller's role in the RBAC config
- Confirm the request targets a cluster ID covered by that role
- Reload vtadmin with the updated config
Example fix
// before
- resource: shard
actions: [get]
// after
- resource: shard
actions: [get, create, delete] Defensive patterns
Strategy: validation
Validate before calling
const canCreateShard = permissions.some(rule => rule.resource === 'shard' && (rule.actions.includes('create') || rule.actions.includes('*')) && (rule.clusters.includes(clusterId) || rule.clusters.includes('*')));
if (!canCreateShard) throw new Error('RBAC denies shard create in ' + clusterId); Type guard
function isShardCreateDenied(err: unknown): boolean {
return err instanceof Error && err.message.includes('cannot create shard');
} Try / catch
try {
await createShard(clusterId, shardReq);
} catch (err) {
if (String(err).includes('cannot create shard')) {
logRbacDenial('shard:create', clusterId);
} else {
throw err;
}
} Prevention
- Ensure the RBAC config defines the shard resource explicitly (missing resource = default deny)
- Pair keyspace and shard permissions when provisioning workflows do both
- Verify cluster scoping per role
When it happens
Trigger: Calling CreateShard (POST /shard) for a cluster whose rules do not grant the caller shard-create permission.
Common situations: Operators allowed to create keyspaces but not shards (resource-scoped RBAC); missing shard resource block entirely in rbac config so default-deny applies; wrong cluster ID in the request.
Related errors
- %w: cannot delete shards 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/260d871fbd5fc91b.
Report an issue: GitHub.