Skip to content

Known AWS gotchas

None of these are cordless bugs exactly, they’re AWS behaviors that are easy to lose an hour to if you don’t already know about them.

Region and architecture can’t change after a function exists

Section titled “Region and architecture can’t change after a function exists”

AWS doesn’t let you move an existing Lambda function to a different region, or flip its architecture (x86_64arm64), in place. There’s no API for it. cordless deploy handles this safely: if you don’t set region/architecture explicitly, a new function gets sensible defaults, but an existing function always keeps whatever it’s already running, so a routine redeploy can never fail with an architecture/region mismatch.

If you actually want to move a bot to a new region or architecture, that means creating a new function under those settings, migrating any data it depends on (DynamoDB tables, S3 buckets), and re-pasting the new endpoint URL into Discord’s Interactions Endpoint URL field. There’s no in-place migration path, because AWS doesn’t have one.

Public Lambda Function URLs need two IAM statements, not one

Section titled “Public Lambda Function URLs need two IAM statements, not one”

If you’re hand-rolling anything around a Function URL outside of cordless deploy (or reading older tutorials), watch for this: AWS started requiring a second resource-policy statement for public (AuthType=NONE) Function URLs in October 2025. The commonly-documented lambda:InvokeFunctionUrl statement alone isn’t enough anymore, you also need a lambda:InvokeFunction statement gated on the InvokedViaFunctionUrl condition key. Without it, every request gets a flat 403 before it ever reaches your handler, which looks a lot like a signature verification failure if you’re testing it through Discord’s endpoint verification, not an IAM problem. cordless deploy grants both statements automatically, and re-grants any missing one on redeploy if a function’s URL was set up by something older that only had the first.

Creating an S3 bucket in us-east-1 via boto3 can fail with IllegalLocationConstraintException

Section titled “Creating an S3 bucket in us-east-1 via boto3 can fail with IllegalLocationConstraintException”

If your setup code creates an S3 bucket with boto3.client("s3") and relies on an ambient region (an environment variable or your AWS config file, no explicit region_name passed to the client), us-east-1 specifically can fail with IllegalLocationConstraintException on create_bucket(). Ambient region resolution routes the client to a regional S3 endpoint, and that endpoint rejects a bucket-creation request with no LocationConstraint, which is exactly the request shape us-east-1 needs (it’s the one region where you must omit the constraint entirely). Passing region_name explicitly when you construct the client sidesteps this, since boto3 then uses the legacy global S3 endpoint instead, which accepts the request correctly.

A deleted S3 bucket name can be flaky to reuse immediately

Section titled “A deleted S3 bucket name can be flaky to reuse immediately”

S3 bucket names are globally unique across every AWS account, not just yours. If you delete a bucket and try to recreate it right away, especially under a different region than it had before, you can hit transient failures while the name propagates as free again. If you’re renaming a project’s AWS resources and a bucket keeps misbehaving right after you delete it, waiting a bit before recreating (or just picking a new name) is often the fastest way through it.