Amazon EC2 API errors
Look up an EC2 API error by code — authorization failures and how to decode their encoded message, capacity and quota errors, not-found errors caused by eventual consistency or the Allowed AMIs setting, and request throttling — each with cause and fix.
markdownreferencev41ATC-M3EPstage: operatetrust: officialservice: ec2interface: anyUnauthorizedOperationEncoded authorization failure messagedecode-authorization-messageDecodeAuthorizationMessagests:DecodeAuthorizationMessageInsufficientInstanceCapacityVcpuLimitExceededInstanceLimitExceededInvalidAMIID.NotFoundAllowed AMIsInvalidGroup.NotFoundInvalidInstanceID.NotFoundeventual consistencyRequestLimitExceedediam:PassRole EC2
EC2 errors have a stable code (UnauthorizedOperation, InvalidAMIID.NotFound, …). Search by the code. Two EC2 habits change how you read them. Authorization failures hide their detail in an encoded message you must decode. And the API is eventually consistent: a resource you just created can be "not found" for a short while.
Authorization
UnauthorizedOperation
An error occurred (UnauthorizedOperation) when calling the RunInstances operation: You are not authorized to perform this operation. Encoded authorization failure message: <long string>
Decode the message:
aws sts decode-authorization-message --encoded-message '<long string>' \
--query DecodedMessage --output text | jq .
- The caller of
decode-authorization-messageneedssts:DecodeAuthorizationMessage. That permission is separate because the decoded message can reveal details of the policies involved. - The decoded JSON says whether access was allowed, the explicit deny if there was one, the denied action, the resource, and the request context (tags, Region, principal).
- On
RunInstances, a frequent cause isiam:PassRoleon the instance profile's role, not an EC2 action. Other common causes: a tag-on-create condition (ec2:CreateTagswithaws:RequestTag), a KMS key for encrypted volumes, or an SCP denying the Region or instance type.
Not every EC2 failure is encoded. AuthFailure concerns the credentials themselves: invalid or expired keys, or a bad signature (UNVERIFIED description in the collected sources). For the general method, see guides/iam/fix-access-denied.md.
Capacity and quotas
| Code | Cause → fix | Check |
|---|---|---|
InsufficientInstanceCapacity | AWS does not currently have enough capacity of that instance type in that Availability Zone. Not your quota. Retry later, use another AZ (another subnet), or another instance type. Spread launches across AZs and types | The same launch in another subnet's AZ succeeds |
VcpuLimitExceeded | The account's vCPU-based quota for that instance family (On-Demand or Spot) would be exceeded. Request an increase in Service Quotas, or stop or terminate instances | aws service-quotas list-service-quotas --service-code ec2 → the family's vCPU quota; sum the vCPUs running |
InstanceLimitExceeded | An instance-count quota would be exceeded (older count-based limits). Same remedy | Same call |
RequestLimitExceeded | The API throttled your request rate. Retry with exponential backoff and jitter. The SDKs retry automatically. Reduce polling; use wait commands or EventBridge events | Calls per second in your code; SDK retry logs |
Not found
| Code | Cause → fix | Check |
|---|---|---|
InvalidAMIID.NotFound | The AMI ID is from another Region, deregistered, or not shared with you. Or the account's Allowed AMIs setting excludes it, in which case the AMI exists but is reported as not found. Prefer resolve:ssm: parameters (guides/ec2/launch-instance.md) | aws ec2 describe-images --image-ids <ami> --region <r>; aws ec2 get-allowed-images-settings |
InvalidAMIID.Malformed | Not a valid ami-… ID (UNVERIFIED code in the collected sources) | The ID's shape: ami- plus hex |
InvalidGroup.NotFound | Security group in another VPC or Region, deleted, or just created and not yet propagated | aws ec2 describe-security-groups --group-ids <sg> --query 'SecurityGroups[0].VpcId' |
InvalidInstanceID.NotFound | Wrong Region, terminated long ago, or just launched. DescribeInstances right after RunInstances can miss it | --region of the call; retry after a few seconds or use aws ec2 wait instance-exists |
InvalidSubnetID.NotFound, InvalidVpcID.NotFound | Wrong Region or ID (UNVERIFIED codes in the collected sources) | aws ec2 describe-subnets --subnet-ids <s> --region <r> |
Eventual consistency
EC2 API changes propagate over a short period. After creating something, retry dependent calls with backoff instead of failing on the first …NotFound. Use aws ec2 wait instance-exists, instance-running or instance-status-ok rather than a fixed sleep.
Request problems
| Code | Cause → fix | Check |
|---|---|---|
InvalidParameterValue / InvalidParameterCombination | Mutually exclusive or invalid options: for example an instance type that the AMI's architecture does not support, or a subnet and security group in different VPCs (UNVERIFIED examples) | aws ec2 describe-images --image-ids <ami> --query 'Images[0].Architecture' vs aws ec2 describe-instance-types --instance-types <t> --query 'InstanceTypes[0].ProcessorInfo.SupportedArchitectures' |
MissingParameter | A required parameter is absent (UNVERIFIED in the collected sources) | The message names the parameter |
DryRunOperation | Not an error: --dry-run would have succeeded. Its opposite, UnauthorizedOperation on a dry run, means it would have failed | None needed |
Reading SDK errors in TypeScript
The AWS SDK for JavaScript v3 throws an error whose name is the code. A retry loop might look like this:
catch (e) {
if (e instanceof Error && e.name === "InvalidInstanceID.NotFound") { /* back off, retry */ }
}
The full code list is on the EC2 error-codes page. This catalogue covers the codes agents hit most.
Launches by Auto Scaling groups and Spot interruptions surface differently, as activity messages: reference/ec2/auto-scaling-and-spot.md.
When none of these fits
Re-run the call with --dry-run, which checks permissions without launching. Decode any Encoded authorization failure message (guides/iam/fix-access-denied.md). Then search CloudTrail for the call's errorCode (guides/cloudtrail/find-who-did-what.md). Capacity errors change by AZ and instance type: try another subnet's AZ or a similar type before opening a case. Keep the request ID.