Debugging AWS Amplify SSR: Unable to Assume IAM Role
TL;DR: If you're getting "Unable to assume specified IAM Role" errors when deploying a Next.js SSR app to AWS Amplify via CLI, stop. Use the Amplify Console UI to create the app and let it generate the service role automatically. CLI-created roles don't work reliably with Amplify SSR builds.
The Problemโ
I was deploying a Next.js 14 app (App Router, SSR) to AWS Amplify Hosting. The app needed to read from DynamoDB, so I set up:
- A DynamoDB table (
FamilyTree) - An IAM role for Amplify with DynamoDB permissions
- Connected my GitHub repo via a Personal Access Token (PAT)
Every single build failed with:
[ERROR]: !!! Unable to assume specified IAM Role. Please ensure the selected
IAM Role has sufficient permissions and the Trust Relationship is configured correctly.
The build never even startedโit failed immediately after "Build environment configured."
What We Tried (None of This Worked)โ
1. Basic Trust Policyโ
Started with the documented trust policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "amplify.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Result: Failed.
2. Added Regional Service Principalโ
Some AWS docs suggest including the regional Amplify endpoint:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"amplify.amazonaws.com",
"amplify.ap-southeast-2.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
Result: Failed.
3. Added CodeBuild Principalโ
Amplify SSR uses CodeBuild under the hood, so maybe it needs that too:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"amplify.amazonaws.com",
"amplify.ap-southeast-2.amazonaws.com",
"codebuild.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
Result: Failed.
4. Attached Every Relevant Policyโ
The role had:
AdministratorAccess-Amplify(AWS managed)AWSCodeBuildAdminAccess(AWS managed)AmplifyBackendDeployFullAccess(AWS managed)- Custom DynamoDB policy for our table
Result: Failed.
5. Checked for Blockersโ
- Service Control Policies (SCPs): Only
FullAWSAccess(default allow-all) - Permission Boundaries: None
- IAM Policy Simulator: Said
sts:AssumeRolewas allowed - CloudTrail: No failed
AssumeRoleevents (error happens inside Amplify's system) - STS Regional Endpoints: Enabled
- Role MaxSessionDuration: 3600 (default)
Result: Everything looked correct. Still failed.
6. Recreated the Appโ
- Deleted the Amplify app
- Created a fresh app with the service role specified from the start
- Re-connected GitHub repo
- Re-added environment variables
Result: Failed with the exact same error.
7. Disassociated and Re-associated the Roleโ
Removed the service role from the app, saved, then re-added it.
Result: Failed.
What Actually Workedโ
Use the Amplify Console UI to create the app.
Instead of:
aws amplify create-app --name "my-app" --platform WEB_COMPUTE ...
Do this:
- Go to AWS Amplify Console โ New app โ Host web app
- Choose GitHub and authorize the AWS Amplify GitHub App (not a PAT)
- Select your repository and branch
- When prompted for Service role, let Amplify create one (or select an existing Amplify-managed role)
- Deploy
The build succeeded on the first try.
The Working Configurationโ
After the console-based setup, Amplify created a service role with surprisingly minimal permissions:
Service Role (created by Amplify Console)โ
- Role name:
AmplifySSRLoggingPolicy-<uuid> - Trust policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "amplify.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
- Permissions policy: Just CloudWatch Logs!
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PushLogs",
"Effect": "Allow",
"Action": ["logs:CreateLogStream", "logs:PutLogEvents"],
"Resource": "arn:aws:logs:ap-southeast-2:*:log-group:/aws/amplify/*:log-stream:*"
},
{
"Sid": "CreateLogGroup",
"Effect": "Allow",
"Action": "logs:CreateLogGroup",
"Resource": "arn:aws:logs:ap-southeast-2:*:log-group:/aws/amplify/*"
},
{
"Sid": "DescribeLogGroups",
"Effect": "Allow",
"Action": "logs:DescribeLogGroups",
"Resource": "arn:aws:logs:ap-southeast-2:*:log-group:*"
}
]
}
Wait, what? The working service role has fewer permissions than our broken one. It only has CloudWatch Logs accessโno AdministratorAccess-Amplify, no CodeBuild permissions, nothing else. Yet it works.
GitHub Connectionโ
- Uses the AWS Amplify GitHub App (not a Personal Access Token)
- This provides more reliable webhook and repository access
Key Differences: CLI vs Consoleโ
| Aspect | CLI-Created (Broken) | Console-Created (Working) |
|---|---|---|
| Service role creation | Manual IAM role | Amplify auto-creates |
| Trust policy | Identical JSON | Identical JSON |
| Attached policies | AdministratorAccess-Amplify + more | Just CloudWatch Logs! |
| GitHub connection | PAT (Personal Access Token) | Amplify GitHub App |
| Build result | FAILED | SUCCESS |
The trust policies were identical. The CLI role had more permissions than the working one. Yet only the console-created setup worked. This strongly suggests the issue isn't about permissions at allโit's about how Amplify internally registers and validates the role association.
Why Does This Happen?โ
The fact that the working role has fewer permissions than our broken one proves this isn't a permissions issue. The trust policies are identical. The broken role had more policies attached.
Root cause: Amplify's internal build system has validation or registration logic that only works correctly when the role is created through the console flow. When you create a role via CLI and attach it to an Amplify app, the ARN is stored, but Amplify's build orchestrator fails to assume itโeven though IAM says it should work.
This appears to be a bug or undocumented requirement in Amplify's SSR (WEB_COMPUTE) platform. Others have reported it:
Lessons Learnedโ
-
For Amplify SSR apps, use the Console UI to create apps. The CLI is fine for static sites, but SSR with
WEB_COMPUTEplatform has quirks. -
Use the Amplify GitHub App, not a PAT. It's more reliable and has proper webhook integration.
-
CloudTrail won't show the failure. The error happens inside Amplify's build orchestration before any AWS API calls are made from your role.
-
The IAM Policy Simulator lies (sort of). It shows the policy would allow the action, but Amplify's internal validation fails before that.
-
"Correct" trust policies aren't enough. Even with
amplify.amazonaws.com,amplify.<region>.amazonaws.com, andcodebuild.amazonaws.comall in the trust policy, CLI-created roles don't work. The working role has fewer permissions than what we tried. -
It's not about permissions. The console-created role only has CloudWatch Logs permissionsโno Amplify admin, no CodeBuild, nothing. Yet it works. Our role with
AdministratorAccess-Amplifyfailed. This is clearly an internal Amplify registration issue, not IAM. -
Document everything before resetting. Having a snapshot of the broken state made it easy to compare and confirm that the working role actually has fewer permissions than what we tried.
Quick Fix Checklistโ
If you hit "Unable to assume specified IAM Role" with Amplify SSR:
- Delete the CLI-created Amplify app
- Go to Amplify Console โ New app โ Host web app
- Connect via GitHub (use Amplify GitHub App, not PAT)
- Let Amplify create the service role
- Add your environment variables in the Console
- Deploy
Don't waste hours debugging IAM like I did. Just use the console.
Environmentโ
- AWS Region: ap-southeast-2
- Amplify Platform: WEB_COMPUTE (SSR)
- Framework: Next.js 14 (App Router)
- Date: January 2026
If this helped you, save someone else the pain and share it.