pulumi/pulumi · error
creating organization role: %w
Error message
creating organization role: %w
What it means
This error wraps failures from POST /api/orgs/{org}/roles, which creates a new custom role. It is thrown by CreateOrgRole in the HTTP-state backend client when restCall fails — network errors, non-2xx status (401/403/409 for duplicates), or malformed server responses.
Source
Thrown at pkg/backend/httpstate/client/client.go:1930
queryObj := struct {
UXPurpose string `url:"uxPurpose,omitempty"`
}{UXPurpose: uxPurpose}
var resp apitype.ListRolesResponse
if err := pc.restCall(ctx, "GET", path, queryObj, nil, &resp); err != nil {
return nil, fmt.Errorf("listing organization roles: %w", err)
}
return resp.Roles, nil
}
// CreateOrgRole creates a new custom role in the given organization.
func (pc *Client) CreateOrgRole(
ctx context.Context, orgName string, req apitype.CreateRoleRequest,
) (apitype.Role, error) {
path := fmt.Sprintf("/api/orgs/%s/roles", url.PathEscape(orgName))
var resp apitype.Role
if err := pc.restCall(ctx, "POST", path, nil, &req, &resp); err != nil {
return apitype.Role{}, fmt.Errorf("creating organization role: %w", err)
}
return resp, nil
}
// GetOrgRole fetches a single custom role by its identifier.
func (pc *Client) GetOrgRole(
ctx context.Context, orgName, roleID string,
) (apitype.Role, error) {
path := fmt.Sprintf("/api/orgs/%s/roles/%s",
url.PathEscape(orgName), url.PathEscape(roleID))
var resp apitype.Role
if err := pc.restCall(ctx, "GET", path, nil, nil, &resp); err != nil {
return apitype.Role{}, fmt.Errorf("getting organization role: %w", err)
}
return resp, nil
}
// UpdateOrgRole updates an existing custom role's name, description, and details.View on GitHub (pinned to 793f7b2e16)
Solutions
- Verify the role name doesn't already exist (list roles first).
- Ensure the token has org admin/owner permissions.
- Confirm the org's subscription includes custom roles.
- Check the wrapped error's HTTP status: 409 → duplicate, 403 → permissions, 400 → invalid payload.
Example fix
// before
if err := pc.restCall(ctx, "POST", path, nil, &req, &resp); err != nil {
return apitype.Role{}, fmt.Errorf("creating organization role: %w", err)
}
// after
var exists apitype.ListRolesResponse
if err := pc.restCall(ctx, "GET", fmt.Sprintf("/api/orgs/%s/roles", url.PathEscape(orgName)), nil, nil, &exists); err == nil {
for _, r := range exists.Roles {
if r.Name == req.Name { return apitype.Role{}, fmt.Errorf("role %q already exists", req.Name) }
}
} Defensive patterns
Strategy: validation
Validate before calling
func validRoleName(name string) bool {
if name == "" || len(name) > 100 { return false }
for _, r := range name {
if !(r == '-' || unicode.IsLetter(r) || unicode.IsDigit(r)) { return false }
}
return true
}
// check existing roles before creating
existing, err := client.ListOrgRole(ctx, org) Try / catch
if err := client.CreateOrgRole(ctx, org, req); err != nil {
var apiErr *apitype.ErrorResponse
if errors.As(err, &apiErr) && apiErr.Code == http.StatusConflict {
return fmt.Errorf("role %q already exists", req.Name)
}
return err
} Prevention
- List existing roles first and skip creation if the name exists.
- Validate role name characters/length before calling the API.
- Ensure the token has org admin permissions.
- Confirm the org's plan supports custom roles.
When it happens
Trigger: Calling CreateOrgRole with an org that lacks custom-roles entitlement, a role name that already exists (409), insufficient permissions, or an invalid CreateRoleRequest payload rejected by the server.
Common situations: Creating a role that already exists; non-admin token; org on a plan without custom roles; submitting role definitions with disallowed characters or missing fields.
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- listing organization roles: %w
- getting organization role: %w
- updating organization role: %w
- deleting organization role: %w
- assigning role to team: %w
AI-assisted analysis of pulumi/pulumi@793f7b2e16 (2026-08-31).
Data as JSON: /api/errors/956eed21a20d2edb.
Report an issue: GitHub.