Wraps Logo
DocsHome
Reference

Error Codes & Troubleshooting

Complete reference for all CLI error codes and SDK error classes, with solutions for each.

CLI Error Codes

Codes that carry a prefix in --json

Most codes reach --json exactly as the tables below list them. Two families are emitted with a prefix added.

  • PULUMI_*: a failure during infrastructure deployment is emitted as PULUMI_ plus the code in the tables, so STACK_LOCKED arrives as PULUMI_STACK_LOCKED. A Pulumi failure the CLI could not classify is emitted as PULUMI_PULUMI_ERROR.
  • AWS_*: an error raised by the AWS SDK itself is emitted as AWS_ plus the SDK's own error name, for example AWS_ExpiredTokenException or AWS_AccessDenied. This family is open-ended and not listed here. The two AWS_* rows in the tables (AWS_THROTTLED, AWS_LIMIT_EXCEEDED) are Wraps' own codes, not members of it.

Match on the documented code. Treat an unrecognised AWS_* or PULUMI_* code as the underlying tool's error, surfaced verbatim.

Credentials & Session

CodeMessageSolution
NO_AWS_CREDENTIALSAWS credentials not foundSet up AWS SSO (aws configure sso), IAM access keys (aws configure), environment variables, or AWS_PROFILE
PROFILE_NOT_FOUNDAWS profile "<profile>" not foundList available profiles, or configure a new one: aws configure --profile <profile>
CREDENTIALS_FILE_MISSINGAWS credentials file not foundSet up AWS SSO, IAM access keys, environment variables, or AWS_PROFILE
ACCESS_KEY_INVALIDAWS access key is invalid or has been deactivatedCheck the IAM console, run aws configure, or generate new access keys
SESSION_TOKEN_EXPIREDAWS session token has expiredSSO users: aws sso login. Assumed roles: re-run your assume-role command
SSO_SESSION_EXPIREDAWS SSO session has expired for profile "<profile>"Run aws sso login --profile <profile>
NOT_AUTHENTICATEDNot authenticated to Wraps PlatformRun wraps auth login, or provide --token / WRAPS_API_KEY
ORG_NOT_FOUNDCould not determine organizationPass --org, or sign in first: wraps auth login

IAM & Permissions

CodeMessageSolution
IAM_PERMISSION_DENIEDPermission denied: <action> on <resource>Your credentials lack the permission. View required permissions: wraps permissions --json
SES_PERMISSION_DENIEDSES permission denied: <action>wraps permissions --service email --json
DYNAMODB_PERMISSION_DENIEDDynamoDB permission deniedNeeds CreateTable, DeleteTable, DescribeTable, UpdateTable
LAMBDA_PERMISSION_DENIEDLambda permission deniedNeeds CreateFunction, UpdateFunctionCode, DeleteFunction
EVENTBRIDGE_PERMISSION_DENIEDEventBridge permission deniedNeeds PutRule, PutTargets, DeleteRule
SQS_PERMISSION_DENIEDSQS permission deniedNeeds CreateQueue, DeleteQueue, GetQueueAttributes
CLOUDWATCH_LOGS_PERMISSION_DENIEDCloudWatch Logs permission deniedNeeds logs:DescribeLogGroups, logs:FilterLogEvents, logs:StartLiveTail
ROUTE53_PERMISSION_DENIEDRoute53 permission deniedNeeds ChangeResourceRecordSets, ListHostedZones (optional — add DNS records manually instead)
IAM_ENTITY_NOT_FOUNDIAM entity not foundRun wraps platform connect

Region & AWS Limits

CodeMessageSolution
INVALID_REGIONInvalid AWS region: <region>Use a valid AWS region like us-east-1, eu-west-1, ap-southeast-1
REGION_REQUIREDRegion is required and could not be determinedPass --region or set AWS_REGION
REGION_REQUIRED_FOR_SETCould not determine which Region to changePass --region <r> with the Region you want to change
AWS_THROTTLEDAWS request was throttledWait and retry. Request a quota increase if this happens repeatedly
AWS_LIMIT_EXCEEDEDAWS service limit exceededRequest a quota increase in Service Quotas

Stack & Deployment

CodeMessageSolution
NO_STACKNo Wraps infrastructure found in this AWS accountRun wraps email init
STACK_EXISTSStack "<stackName>" already existsTo update: wraps email upgrade. To remove: wraps destroy --stack <stackName>
STACK_LOCKEDThe Pulumi stack is locked from a previous runRemove ~/.wraps/pulumi/.pulumi/locks (local), or delete the lock object under .pulumi/locks/ in your wraps-state-* bucket (S3)
PENDING_OPERATIONSThe Pulumi stack has unresolved operations from a previous deploymentRun pulumi refresh to reconcile state, or pulumi stack export to inspect it. If a deployment is genuinely still running elsewhere, wait for it instead.
PULUMI_ERRORInfrastructure deployment failed: <message>The message above is Pulumi's own output. Re-run the command if it looks transient; see the troubleshooting guide if it persists.
PULUMI_NOT_INSTALLEDPulumi CLI is not installedInstall via brew/curl/choco, or download from pulumi.com/docs/install
RESOURCE_CONFLICTResource already exists: <resourceName>Diagnose first: wraps email doctor. Only run --cleanup if it lists orphaned resources.
S3_STATE_BUCKET_CREATION_FAILEDFailed to create S3 state bucket: <bucketName>Ensure s3:CreateBucket, s3:PutBucketEncryption, s3:PutBucketVersioning, or export WRAPS_LOCAL_ONLY=1
S3_STATE_ACCESS_DENIEDAccess denied to S3 state bucketEnsure s3:GetObject, s3:PutObject, s3:ListBucket on wraps-state-*, or export WRAPS_LOCAL_ONLY=1
STATE_MIGRATION_FAILEDFailed to migrate Pulumi state to S3Local state is still intact. export WRAPS_LOCAL_ONLY=1 to skip migration
SELFHOST_NO_LOG_GROUPSNo self-hosted log groups found in <region>Check wraps selfhost status, or target a different region
SELFHOST_NO_LOG_GROUPS_FOR_SOURCENo <source> log groups in this deploymentDrop the filter: wraps selfhost logs
LAMBDA_FUNCTION_NOT_FOUNDAgent enforcer Lambda not foundDeploy it: wraps email agent create
DYNAMODB_TABLE_NOT_FOUNDAgent policy table not foundDeploy it: wraps email agent create

Email / SES

CodeMessageSolution
SES_MESSAGE_REJECTEDSES rejected the message: <detail>Sandbox with unverified recipient, unverified sender identity, or receiving-only domain. Check wraps email status / wraps email doctor
SES_MAIL_FROM_NOT_VERIFIEDSES MAIL FROM domain is not verified: <detail>Check DNS records: wraps email verify
SES_ACCOUNT_SENDING_PAUSEDSES account-level sending is pausedCheck the SES console Reputation Dashboard
SES_CONFIG_SET_SENDING_PAUSEDSES configuration set sending is pausedResume it in the SES console, or send without that configuration set
SES_CONFIG_SET_MISSINGSES configuration set does not exist: <detail>Create it in the SES console, switch regions, or remove ConfigurationSetName
EVENT_DESTINATION_NOT_FOUNDEvent destination not found for <domain>Run wraps email upgrade
INVALID_EVENT_DESTINATIONEvent destination for <domain> is not an EventBridge destinationRun wraps email upgrade
EVENT_TYPES_MISSING_SUPPRESSION_EVENTSeventTracking.events is missing required event type(s): <missing>BOUNCE and COMPLAINT must always be included in eventTracking.events
INVALID_SES_PRICING_PLANNo pricing plan specifiedPass --set with one of the valid pricing plans
SES_PRICING_PLAN_CHANGE_REJECTEDSES rejected the pricing plan change: <detail>Check the current plan: wraps email plan
SES_VDM_CHANGE_REJECTEDSES rejected the VDM change: <detail>Check the current state: wraps email vdm
INVALID_VALIDATION_THRESHOLDInvalid validation threshold: <detail>Valid values: medium, high, managed
SUPPRESSION_OPTIONS_MISSINGConfiguration set <name> has no suppression options, so Auto Validation cannot be added without changing its suppression behaviourSet suppression explicitly first: wraps email domains config --suppress-bounce --suppress-complaint
CONFLICTING_VDM_FLAGSPass either --enable or --disable, not bothUse one of the two flags
SENDING_POOL_CONFLICTThe configuration set already sends through dedicated IP pool "<pool>"Wraps will not replace a pool it did not attach. Detach it in the SES console or leave managed dedicated IPs off.
MANAGED_POOL_NAME_TAKENA STANDARD dedicated IP pool named "wraps-email-managed" already existsWraps will not convert it (MANAGED is irreversible). Rename or delete that pool, then retry.
MANAGED_DEDICATED_IPS_UNAVAILABLEManaged dedicated IPs are unavailable on your SES plan: <reason>Check your current SES pricing plan: wraps email plan
PRODUCTION_ACCESS_PENDINGA production access request is already under review for this accountWait for AWS to finish the current review before submitting another. Run wraps email production-access to see its status.
PRODUCTION_ACCESS_REJECTEDAWS rejected the request: <detail>Check the website URL (must be a full https:// URL) and contact addresses, then retry.
PRODUCTION_ACCESS_ALREADY_ENABLEDProduction access is already enabled for this account in <region>Nothing to do — run wraps email production-access to confirm
INVALID_WEBSITE_URLInvalid --website: <value>Pass a full URL starting with http:// or https://, up to 1000 characters
INVALID_MAIL_TYPEInvalid --mail-type: <value>Valid values: transactional, marketing
INVALID_CONTACT_EMAILInvalid contact email: <value>Pass valid email addresses, comma-separated, via --contact (max 4)

Tracking Domains

CodeMessageSolution
INVALID_TRACKING_DOMAINInvalid --tracking-domain: <problem>A tracking domain must be a hostname under the sending domain, e.g. track.news.example.com for news.example.com
PRIMARY_TRACKING_DOMAIN_MANAGED_BY_PULUMI<domain> is the primary domain — its tracking domain is managed by wraps email upgradeRun wraps email upgrade and choose "tracking". domains config sets tracking domains on additional domains only.
TRACKING_DOMAIN_REQUIRED<domain> has no tracking domain yetSet one before enabling HTTPS: wraps email domains config --domain <domain> --tracking-domain <host>
PRIMARY_TRACKING_HTTPS_MANAGED_BY_PULUMI<domain> is the primary domain — its HTTPS tracking is managed by wraps email upgradeRun wraps email upgrade and choose "tracking"
TRACKING_HTTPS_PROVISION_FAILEDFailed to provision HTTPS for tracking domain: <detail>Usually the ACM certificate is not ISSUED yet (validation takes 5-30 minutes), the tracking domain is already claimed by another CloudFront distribution, or the account lacks acm:RequestCertificate / cloudfront:CreateDistributionWithTags. Retry with wraps email domains config --domain <domain> --tracking-https.

Inbound Email

CodeMessageSolution
INBOUND_REGION_NOT_SUPPORTEDSES email receiving is not supported in <region>Deploy in us-east-1, us-west-2, or eu-west-1
INBOUND_REQUIRES_OUTBOUNDInbound email requires outbound email infrastructureRun wraps email init, then wraps email inbound init
RECEIPT_RULE_SET_CONFLICTAnother receipt rule set is active: <activeRuleSet>Wraps will activate wraps-inbound-rules, deactivating the current set
INBOUND_MX_CONFLICT<domain> already has mail routed to itPick a subdomain with no existing MX record, e.g. wraps email inbound add --subdomain support. Or run interactively (without --yes) to confirm and proceed anyway.
INBOUND_TEST_SEND_FAILEDFailed to send inbound test email to <recipient>Check wraps email status / wraps email doctor
INBOUND_TEST_MAIL_FROM_NOT_VERIFIEDCustom MAIL FROM domain is not verified for <domain>Verify DNS records: wraps email verify
INBOUND_TEST_MESSAGE_REJECTEDSES rejected the inbound test send: <message>Sandbox with unverified recipient, unverified sender domain, or receiving-only domain. Check wraps email status / doctor
INBOUND_TEST_SENDING_PAUSEDSES sending is paused for this accountCheck the SES console Reputation Dashboard
INBOUND_TEST_PERMISSION_DENIEDIAM permission denied: ses:SendEmail in <region>wraps permissions --service email --json

Reply Threading

CodeMessageSolution
REPLY_SECRET_PARAMETER_MISSINGSSM parameter for <domain> was not createdRun wraps email reply status to diagnose, or retry the init
REPLY_REQUIRES_INBOUNDReply threading requires inbound email infrastructureDeploy inbound first: wraps email inbound init
REPLY_NO_INBOUND_DOMAINSNo inbound domains configuredAdd one: wraps email inbound add --domain yourapp.com
REPLY_INBOUND_DOMAIN_NOT_FOUNDDomain <target> is not configured for inbound emailAdd it to inbound first: wraps email inbound add <target>
REPLY_ALREADY_ENABLEDReply threading is already enabled for <target>To rotate the signing secret: wraps email reply rotate --domain <target>
REPLY_MISSING_DOMAINSpecify a domain or use --allwraps email reply init --domain yourapp.com, or --all
REPLY_ROTATE_MISSING_DOMAIN--domain is required for rotatewraps email reply rotate --domain yourapp.com
REPLY_NOT_ENABLEDReply threading is not enabledEnable it first: wraps email reply init --domain yourapp.com
REPLY_DOMAIN_NOT_ENABLEDReply threading is not enabled for <domain>Enable it first: wraps email reply init --domain <domain>
REPLY_DESTROY_MISSING_DOMAINSpecify a domain or use --allwraps email reply destroy --domain yourapp.com, or --all
REPLY_DECODE_MISSING_ADDRESSUsage: wraps email reply decode <token>@r.mail.yourapp.comProvide a signed reply address
REPLY_DECODE_MALFORMED_ADDRESSAddress must be in the form <token>@r.mail.example.comPass a full signed reply address

SMS

CodeMessageSolution
SMS_NOT_CONFIGUREDSMS infrastructure not foundRun wraps sms init
SMS_PHONE_NOT_VERIFIEDPhone number registration not completeToll-free numbers require registration (15+ days). Check status in the AWS console
SMS_OPTED_OUTDestination number <phoneNumber> has opted outThe recipient can opt back in by texting START
SMS_SPENDING_LIMITAWS SMS spending limit reachedRequest a spending limit increase in the AWS console
SMS_INVALID_PHONE_NUMBERInvalid phone number format: <phoneNumber>Use E.164 format, e.g. +14155551234
SMS_INVALID_COUNTRIESInvalid --countries value: <raw>Comma-separated ISO 3166-1 alpha-2 codes, e.g. --countries US,CA,GB
SMS_INVALID_VOLUMEInvalid --volume value: <raw>Positive whole number of messages per month
SMS_SIMULATOR_LIMITSimulator daily message limit reached (100 messages)Upgrade: wraps sms upgrade --phone-type toll-free

SMTP

CodeMessageSolution
SMTP_CREDENTIALS_NOT_FOUNDSMTP credentials not foundwraps email upgrade and select "Enable SMTP credentials"
SMTP_REQUIRES_SENDINGSMTP credentials require email sending to be enabledwraps email upgrade and select "Custom configuration"

Templates & Config

CodeMessageSolution
WRAPS_CONFIG_NOT_FOUNDwraps/wraps.config.ts not foundInitialize templates first: wraps email templates init
TEMPLATE_COMPILATION_FAILEDFailed to compile template "<name>": <error>Check your template for syntax errors and valid imports
TEMPLATE_PUSH_FAILEDFailed to push template "<name>": <error>Check your API key and network connection
TEMPLATES_DIR_EXISTSwraps/ directory already existsUse --force to overwrite: wraps email templates init --force

CLI Usage & Automation

CodeMessageSolution
NON_INTERACTIVE_INPUT<what> is required in non-interactive modePass the required flag, or run in an interactive terminal
UNKNOWN_COMMANDUnknown <command kind>: <what was typed>Run wraps --help, or use one of the commands listed in the error's suggestion
MISSING_REQUIRED_FLAGA required flag is missing in JSON modeProvide the flag named in the error message
JSON_REQUIRES_FORCE--force flag is required in JSON mode for destructive operationsAdd --force to the command
CONFIRMATION_REQUIREDConfirmation required to change your SES pricing planPass --yes to skip the confirmation prompt
OPERATION_CANCELLEDOperation cancelledPass --region to skip the interactive prompt
INVALID_LOG_SOURCEUnknown --source value: <value>Valid sources: api, web, workers, other, all
INVALID_LOG_WINDOWInvalid --since value: <value>Use a positive number followed by s, m, h, or d
UNKNOWN_ERRORAn unexpected error occurredThe thrown value was not a recognized WrapsError. Check the CLI logs for details

Exit Codes

Every command exits 0 on success and 1 on error, with one exception.

CommandExit codeMeaning
Any command0Success
Any command1Error
wraps email check0Deliverability grade A or B
wraps email check1Deliverability grade C or D
wraps email check2Deliverability grade F
wraps email check4Check itself failed to run, or grade was unrecognized

In --json mode, errors are still written to stdout as a JSON envelope — the exit code is what signals failure to scripts:

JSONerror-envelope.json
{  "success": false,  "command": "email.init",  "error": {    "code": "<error code — see below>",    "message": "...",    "suggestion": "...",    "docsUrl": "https://wraps.dev/docs/..."  }}

SDK Error Classes

Email SDK (@wraps.dev/email)

WrapsEmailError

Base class every other email SDK error extends. Use it for a single catch-all instanceof check that covers all of them.

SESError

Thrown when an AWS SES API call fails.

PropertyTypeDescription
codestringMessageRejected, Throttling, AccountSuspended, MailFromDomainNotVerified
requestIdstringAWS request identifier
retryablebooleanWhether the request can be retried
DynamoDBError

Thrown when an email history read/write operation fails.

PropertyTypeDescription
codestringDynamoDB error code
requestIdstringAWS request identifier
retryablebooleanWhether the request can be retried
ValidationError

Thrown when input parameters are invalid.

PropertyTypeDescription
fieldstringWhich field failed validation
messagestringHuman-readable error description
CredentialsError

The AWS credential chain produced nothing usable, so no request was ever signed. The message lists every way to supply credentials — SSO, access keys, environment variables, a named profile, or the constructor — without ranking one over another.

PropertyTypeDescription
causeunknownThe underlying AWS SDK error, for debugging
SandboxError

Extends SESError. SES rejected the send because an identity involved is not verified in the region the request went to. Two unrelated causes produce this one AWS error — a region mismatch and the SES sandbox — so the message names the region actually used and walks through both, including the mailbox-simulator address that proves sending works without production access.

PropertyTypeDescription
regionstring | undefinedThe region this client sent to, when resolvable

SMS SDK (@wraps.dev/sms)

WrapsSMSError

Base class every other SMS SDK error extends. Use it for a single catch-all instanceof check that covers all of them.

SMSError

Thrown when an AWS End User Messaging API call fails.

PropertyTypeDescription
codestringAWS error code
retryablebooleanWhether the request can be retried
ValidationError

Thrown when input parameters are invalid.

PropertyTypeDescription
fieldstringWhich field failed validation
messagestringHuman-readable error description
OptedOutError

Thrown when the recipient has opted out of receiving messages.

PropertyTypeDescription
phoneNumberstringThe phone number that opted out
RateLimitError

Thrown when the sending rate limit has been exceeded.

PropertyTypeDescription
retryAfternumberSeconds to wait before retrying

No Automatic Retries

The SDKs do NOT automatically retry failed requests. If retryable is true, implement your own retry logic using the pattern below.

Retry Pattern

Use exponential backoff when retrying failed requests. This example uses a simple retry loop with increasing delays.

TypeScriptretry-pattern.ts
import { WrapsEmail, SESError } from '@wraps.dev/email';const email = new WrapsEmail();async function sendWithRetry(params, maxRetries = 3) {  for (let attempt = 0; attempt < maxRetries; attempt++) {    try {      return await email.send(params);    } catch (error) {      if (error instanceof SESError && error.retryable && attempt < maxRetries - 1) {        await new Promise(r => setTimeout(r, Math.pow(2, attempt) * 1000));        continue;      }      throw error;    }  }}

Error Handling Example

Catch and handle specific error types to provide appropriate responses in your application.

TypeScripterror-handling.ts
import { WrapsEmail, SESError, DynamoDBError, ValidationError } from '@wraps.dev/email';const email = new WrapsEmail();try {  await email.send({    from: 'hello@yourdomain.com',    to: 'user@example.com',    subject: 'Hello',    html: '<p>Hello!</p>',  });} catch (error) {  if (error instanceof ValidationError) {    console.error('Invalid input:', error.field, error.message);  } else if (error instanceof SESError) {    console.error('SES error:', error.code, error.retryable);  } else if (error instanceof DynamoDBError) {    console.error('DynamoDB error:', error.code, error.retryable);  }}

Next Steps

Email SDK

Full API reference for the @wraps.dev/email TypeScript SDK.

View Reference
SMS SDK

Full API reference for the @wraps.dev/sms TypeScript SDK.

View Reference
AWS Setup

Configure AWS credentials and permissions for Wraps.

View Guide