floci-io/floci · error · AwsException
ValidationError
ValidationError
Error message
Updating RoleName requires resource replacement, which is not supported.
What it means
ValidationError from the AWS::IAM::Role provisioner when an update resolves a different RoleName than the one recorded at create time. RoleName is a replacement property in AWS and the emulator does not model replacement here, so a mismatch is rejected instead of creating a second role.
Source
Thrown at src/main/java/io/github/hectorvent/floci/services/cloudformation/provisioners/IamRoleCfnProvisioner.java:58
}
@Override
public Set<String> resourceTypes() {
return Set.of("AWS::IAM::Role");
}
@Override
public void provision(StackResource r, JsonNode props, ProvisionContext ctx) {
String existingRoleName = r.getPhysicalId();
String roleName = ctx.resolveOptional(props, "RoleName");
if (roleName == null || roleName.isBlank()) {
roleName = existingRoleName != null && !existingRoleName.isBlank()
? existingRoleName
: ctx.generatePhysicalName(r.getLogicalId(), 64, false);
}
final String resolvedRoleName = roleName;
if (existingRoleName != null && !existingRoleName.equals(resolvedRoleName)) {
throw new AwsException("ValidationError",
"Updating RoleName requires resource replacement, which is not supported.", 400);
}
String assumeDoc = props != null && props.has("AssumeRolePolicyDocument")
? props.get("AssumeRolePolicyDocument").toString()
: "{\"Version\":\"2012-10-17\",\"Statement\":[]}";
String path = ctx.resolveOptional(props, "Path");
if (path == null) {
path = "/";
}
String description = ctx.resolveOptional(props, "Description");
List<String> managedPolicyArns = ctx.resolveStringList(props, "ManagedPolicyArns");
IamRole role;
boolean createdRole = false;
// Set only on the adoption path, to the role's trust policy (and verified RoleId) as they
// were before this attempt touched them. Lets a later failure (e.g. bad ManagedPolicyArns)
// restore the trust policy below, so a rolled-back update doesn't leave it changed despite
// UPDATE_ROLLBACK_COMPLETE - and restore it onto the *same verified role*, not onto aView on GitHub (pinned to 62ff490619)
Solutions
- Keep RoleName identical across updates, or omit it in every version of the template.
- If a rename is required, treat it as replacement: delete and recreate the stack or move the role to a new logical id.
- Note the same asymmetry as other named resources: once created unnamed, the generated name is sticky and adding a declared name always fails.
Example fix
# before (v1 had no RoleName, v2 adds one) Type: AWS::IAM::Role Properties: RoleName: app-role # != generated physical id # after (keep consistent across versions) Type: AWS::IAM::Role Properties: # no RoleName in any version; or set it in v1 from the start AssumeRolePolicyDocument: ...
Defensive patterns
Strategy: validation
Validate before calling
String declared = template.stringAt("Resources/Role/Properties/RoleName");
String recorded = describeStackResource(stack, "Role").physicalResourceId();
if (declared != null && !declared.equals(recorded)) {
throw new IllegalStateException("RoleName change requires stack recreation");
} Try / catch
catch ValidationError "Updating RoleName requires resource replacement": revert RoleName in the template, or recreate (new logical id / new stack); the update itself can never succeed.
Prevention
- Set RoleName once at first deploy or never set it
- Never add a RoleName to a resource that was previously created unnamed
- Model renames as explicit delete+create in deployment pipelines
When it happens
Trigger: UpdateStack where the template's RoleName differs from the stack resource's physical id — adding a RoleName to a role that was originally created unnamed (generated name), or editing the declared name.
Common situations: Templates versioned over time that introduce or rename RoleName; environments where a role first deployed without an explicit name is later tightened to carry one.
Understand the failure class
Background: ValidationError explained: why open-source libraries reject your input — file uploads, YAML manifests, unique fields, and query permissions — this error's family across 13 libraries.
Related errors
AI-assisted analysis of floci-io/floci@62ff490619 (2026-08-14).
Data as JSON: /api/errors/f637fb6b6bd82a18.
Report an issue: GitHub.