aws-amplify / aws-amplify/amplify-cli

Storage deploy fails with 'Policy resource was already managed by another stack' after CFN enforcement change (Jan 2026)

Open
#14,961 0 comments 0 reactions 1 assignee Claimed by @sharonyajain View on GitHub
bug
Dominant language
TypeScript
Stars
2.9k
Forks
825
Avg merge
11d 23h
Merged PRs (30d)
2

Description

## 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---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:
1. **Same PolicyName** — guaranteed by the shared `policyUUID` across envs
2. **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:

```typescript
// 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`:

```typescript
// 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

- #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

- 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)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.