{"record":{"id":"26a60f72bccf3536","repo":"anomalyco/sst","slug":"lambda-edge-requires-a-qualified-arn-with-version","errorCode":null,"errorMessage":"Lambda@Edge requires a qualified ARN (with version). Got: ${arn}","messagePattern":"Lambda@Edge requires a qualified ARN \\(with version\\)\\. Got: (.+?)","errorType":"validation","errorClass":"VisibleError","httpStatus":null,"severity":"error","filePath":"platform/src/components/aws/helpers/arn.ts","lineNumber":127,"sourceCode":"}\n\nexport function parseLambdaEdgeArn(arn: string) {\n  // First validate it's a Lambda function ARN\n  const { functionName } = parseFunctionArn(arn);\n\n  // arn:aws:lambda:region:account-id:function:function-name:version\n  const parts = arn.split(\":\");\n  const region = parts[3];\n  const version = parts[7];\n\n  if (region !== \"us-east-1\") {\n    throw new VisibleError(\n      `Lambda@Edge functions must be deployed in us-east-1 region. Got region: ${region}`,\n    );\n  }\n\n  if (!version || version === \"$LATEST\") {\n    throw new VisibleError(\n      `Lambda@Edge requires a qualified ARN (with version). Got: ${arn}`,\n    );\n  }\n\n  return { functionName, region, version };\n}\n\nexport function parseElasticSearch(arn: string) {\n  // arn:aws:es:region:account-id:domain/domain-name\n  const tableName = arn.split(\"/\")[1];\n  if (!arn.startsWith(\"arn:\") || !tableName)\n    throw new VisibleError(\n      `The provided ARN \"${arn}\" is not a ElasticSearch domain ARN.`,\n    );\n  return { tableName };\n}\n\nexport function parseOpenSearch(arn: string) {","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/anomalyco/sst/blob/a0bd20f762883e72a35caccb4896c42ce5b3f707/platform/src/components/aws/helpers/arn.ts#L109-L145","documentation":"Lambda@Edge can only be attached to a CloudFront distribution via a versioned function ARN; $LATEST or an unqualified ARN is rejected by AWS. parseLambdaEdgeArn extracts parts[7] (the version) and throws a VisibleError when it is missing or equals \"$LATEST\".","triggerScenarios":"Passing a bare function ARN like arn:aws:lambda:us-east-1:123456789:function:name (no version suffix), or one ending in :$LATEST, to a Lambda@Edge/CloudFront option handled by normalizeProtection.","commonSituations":"Copying the function ARN from the AWS console (which shows the unqualified ARN) instead of the version ARN; referencing a function alias not a published version; forgetting to publish a version after updating code.","solutions":["Publish a version of the Lambda and use the qualified ARN ending in :<version-number>","In SST, reference the function's version output rather than the raw arn","Never use $LATEST for edge functions; pin an explicit version"],"exampleFix":"// before\nedge: \"arn:aws:lambda:us-east-1:123456789012:function:myFn:$LATEST\"\n// after\nedge: \"arn:aws:lambda:us-east-1:123456789012:function:myFn:3\"","handlingStrategy":"validation","validationCode":"function assertVersionedArn(arn: string) {\n  const version = arn.split(\":\")[7];\n  if (!version || version === \"$LATEST\") throw new Error(`ARN must have a version: ${arn}`);\n}","typeGuard":"const isQualifiedArn = (arn: string) => { const v = arn.split(\":\")[7]; return !!v && v !== \"$LATEST\"; };","tryCatchPattern":null,"preventionTips":["Always publish versions for edge lambdas","Reference the version output, not the raw arn","Reject $LATEST in config validation"],"tags":["lambda-edge","arn","versioning","cloudfront"],"backgroundTag":"lambda-edge-unqualified-arn","analyzedSha":"a0bd20f762883e72a35caccb4896c42ce5b3f707","analyzedAt":"2026-08-30T11:26:00.383Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}