Description
As of January 30, 2026, CloudFormation enforces single-stack ownership of IAM inline policies. This breaks amplify push for Gen1 projects with multiple environments that share storage resources targeting the same IAM role (e.g., when using imported Identity Pool/auth roles).
The deploy fails with:
The following resource(s) failed to update: [S3AuthUploadPolicy, S3AuthPublicPolicy, S3AuthProtectedPolicy, S3AuthReadPolicy, S3AuthPrivatePolicy]
Policy resource was already managed by another stack or another resource in the current stack. Found stacks: [amplify-<app>-<env2>-storage...|S3AuthPrivatePolicy]
Root Cause
When amplify env add creates a new environment, it copies cli-inputs.json verbatim — including the policyUUID field. This UUID is generated once (in s3-defaults.ts via buildShortUUID()) when storage is first added to the project. All environments therefore produce identical policy names (e.g., Private_policy_ad0f22e8).
This only becomes a problem when both conditions are met:
- Same PolicyName — guaranteed by the shared
policyUUID across envs
- Same target IAM role — occurs when environments share auth roles (e.g., imported Identity Pool with shared authenticated/unauthenticated roles, or manually configured shared roles)
In the common case where each environment has its own auth roles (the default for amplify add auth), the identical policy names land on different roles, and CFN does not conflict. This is why relatively few customers hit it — it requires a shared-role configuration.
Affected Code
packages/amplify-category-storage/src/provider-utils/awscloudformation/cdk-stack-builder/s3-stack-transform.ts (lines 115-121) — policy names use policyUUID without envName differentiation
amplify env add clones cli-inputs.json (containing policyUUID) to new environments unchanged
Workaround
Use amplify override storage in each affected environment to make policy names unique:
// override.ts
import { AmplifyS3ResourceTemplate } from "@aws-amplify/cli-extensibility-helper";
export function override(resources: AmplifyS3ResourceTemplate) {
const envName = "YOUR_ENV_NAME"; // e.g., "dev", "prod"
resources.s3AuthPrivatePolicy.policyName += `-${envName}`;
resources.s3AuthProtectedPolicy.policyName += `-${envName}`;
resources.s3AuthPublicPolicy.policyName += `-${envName}`;
resources.s3AuthReadPolicy.policyName += `-${envName}`;
resources.s3AuthUploadPolicy.policyName += `-${envName}`;
}
Then run amplify push. Repeat for each environment with a different envName value.
Suggested Fix
Append the environment name to the policyUUID when generating CFN parameters in s3-stack-transform.ts:
// Before:
this.cfnInputParams.s3PrivatePolicy = `Private_policy_${userInput.policyUUID}`;
// After:
this.cfnInputParams.s3PrivatePolicy = `Private_policy_${userInput.policyUUID}_${envName}`;
This prevents new occurrences. Existing affected stacks still need the override workaround above.
Related
Environment
- Amplify CLI: current (latest on
dev)
- Trigger: CFN enforcement change Jan 30, 2026
- Frequency: Low — only affects projects with shared auth roles across environments (imported Identity Pool or manual role configuration)
Description
As of January 30, 2026, CloudFormation enforces single-stack ownership of IAM inline policies. This breaks
amplify pushfor Gen1 projects with multiple environments that share storage resources targeting the same IAM role (e.g., when using imported Identity Pool/auth roles).The deploy fails with:
Root Cause
When
amplify env addcreates a new environment, it copiescli-inputs.jsonverbatim — including thepolicyUUIDfield. This UUID is generated once (ins3-defaults.tsviabuildShortUUID()) when storage is first added to the project. All environments therefore produce identical policy names (e.g.,Private_policy_ad0f22e8).This only becomes a problem when both conditions are met:
policyUUIDacross envsIn the common case where each environment has its own auth roles (the default for
amplify add auth), the identical policy names land on different roles, and CFN does not conflict. This is why relatively few customers hit it — it requires a shared-role configuration.Affected Code
packages/amplify-category-storage/src/provider-utils/awscloudformation/cdk-stack-builder/s3-stack-transform.ts(lines 115-121) — policy names usepolicyUUIDwithout envName differentiationamplify env addclonescli-inputs.json(containingpolicyUUID) to new environments unchangedWorkaround
Use
amplify override storagein each affected environment to make policy names unique:Then run
amplify push. Repeat for each environment with a differentenvNamevalue.Suggested Fix
Append the environment name to the
policyUUIDwhen generating CFN parameters ins3-stack-transform.ts:This prevents new occurrences. Existing affected stacks still need the override workaround above.
Related
Authenticated rolein an imported Identity Pool #10098 — same root cause (shared policyUUID + shared roles), different symptom (policy content overwriting rather than CFN rejection). A fix that appends envName to policy names would address both issues.Environment
dev)