ResourceNotFoundException: Requested resource not found

Short answer

The service looked for the named resource and did not find it. Nine times in ten the resource exists — just not in the region or account the function is calling into, which is the one possibility the message cannot tell you about.

What it means

ResourceNotFoundException is one of the most-encountered errors in AWS and one of the least informative, because the thing it most often means is the thing it cannot say. The service checked for the resource you named, in the account it was called from and the region it was called in, and did not find it. It has no way of knowing the resource exists perfectly well somewhere else.

Region is the usual answer. An SDK client constructed without an explicit region takes it from AWS_REGION, which the execution environment sets to wherever the function is deployed. That is almost always what you want, and it means the same code targets us-east-1 in one deployment and eu-west-1 in another without anything in the source suggesting a region is involved. Code developed against a hardcoded region, or a client copied from a script that set one, changes behaviour on deploy in a way nothing in the diff shows.

The second recurring cause is a name that is empty. An environment variable that was never set resolves to undefined, gets passed as the table or queue name, and produces a not-found for a resource with no name at all. Read closely, the message often shows this — there is simply nothing between the colon and the words "not found" — but it reads as a formatting quirk rather than as the answer.

The subtlety worth carrying is that not-found and access-denied are not always distinct. Several AWS services deliberately return ResourceNotFoundException when the caller has no permission to know the resource exists, because confirming existence to an unauthorised caller is itself a small information leak. So a resource you can see in the console, in the right account and the right region, that the function insists is not there, may be a permissions problem wearing a not-found message. Checking the execution role before assuming a deployment problem is worth the minute it takes.

Depends

CloudWatch’s Errors metric: Whether CloudWatch’s Errors metric counts this depends on whether the error escaped your handler, which the log line alone does not settle. Counted only when the exception escapes the handler. This is deterministic rather than transient, so affected requests fail consistently. LogStitch reports the example below as caught.

What it looks like in CloudWatch

This is the shape the failure arrives in: the lines of one invocation scattered among everything else the log group received at the same moment.

CloudWatch Logs Before

7 raw lines, in the order CloudWatch delivered them.

2026-08-30T16:31:44.114Z START RequestId: 3b8d5f02-6a17-4e40-9c25-8f1a7b3e0d62 Version: $LATEST
2026-08-30T16:31:44.118Z 3b8d5f02-6a17-4e40-9c25-8f1a7b3e0d62 INFO Looking up order ord_92ba7c
2026-08-30T16:31:44.244Z 3b8d5f02-6a17-4e40-9c25-8f1a7b3e0d62 ERROR ResourceNotFoundException: Requested resource not found: Table: orders not found
at throwDefaultError (/var/task/node_modules/@smithy/smithy-client/dist-cjs/index.js:867:20)
at loadOrder (/var/task/src/orders.js:24:9)
2026-08-30T16:31:44.402Z END RequestId: 3b8d5f02-6a17-4e40-9c25-8f1a7b3e0d62
2026-08-30T16:31:44.402Z REPORT RequestId: 3b8d5f02-6a17-4e40-9c25-8f1a7b3e0d62 Duration: 288.44 ms Billed Duration: 289 ms Memory Size: 512 MB Max Memory Used: 94 MB Status: error

LogStitch After

The same lines, grouped into the invocation they belong to.

Error3b8d5f02-6a17-4e40-9c25-8f1a7b3e0d62dur 288msbilled 289msmem 94/512MBlogs 5
  1. 16:31:44.114PLAT
    START RequestId: 3b8d5f02-6a17-4e40-9c25-8f1a7b3e0d62 Version: $LATEST
  2. 16:31:44.118INFO
    INFO	Looking up order ord_92ba7c
  3. 16:31:44.244ERROR
    ERROR	ResourceNotFoundException: Requested resource not found: Table: orders not found
        at throwDefaultError (/var/task/node_modules/@smithy/smithy-client/dist-cjs/index.js:867:20)
        at loadOrder (/var/task/src/orders.js:24:9)
    3 lines
  4. 16:31:44.402PLAT
    END RequestId: 3b8d5f02-6a17-4e40-9c25-8f1a7b3e0d62
  5. 16:31:44.402PLAT
    REPORT RequestId: 3b8d5f02-6a17-4e40-9c25-8f1a7b3e0d62	Duration: 288.44 ms	Billed Duration: 289 ms	Memory Size: 512 MB	Max Memory Used: 94 MB	Status: error
Error
Status
288ms
Duration
289ms
Billed
94/512MB
Memory
82%
Headroom
No
Cold start
LogLevelError
Error type

The panel on the right is generated by running the excerpt on the left through the same parser that powers the free web stitcher — it is what the tool actually produces for this input, not an illustration of it.

How to confirm it from the logs

Read the resource identifier in the message and check its region and account. If it is an ARN, both are in it and the comparison is direct. If it is a bare name — a table, a queue, a secret — the region is implicit in the client's configuration, which means the message cannot show you the thing most likely to be wrong.

Distinguish it from a permissions failure, because the two are easy to confuse and IAM sometimes chooses this deliberately. AccessDeniedException says you may not; ResourceNotFoundException says there is nothing there. But some services return not-found rather than denied when the caller has no permission to know the resource exists, so a resource you can see in the console and the function cannot find is worth checking as a permissions problem too.

Causes, most likely first

1

The function and the resource are in different regions

How to confirm

Compare the region in the resource ARN, or the client's configured region, against the function's region. An SDK client with no explicit region uses AWS_REGION from the execution environment, so code that worked against a hardcoded region locally silently targets a different one in production.

2

The resource name comes from an environment variable that is unset

How to confirm

Check whether the name in the message is empty, literally undefined, or a placeholder. An unset variable produces a lookup for a resource that was never going to exist, and the message shows the empty name if you read it closely.

3

The resource was renamed, deleted, or never deployed to this environment

How to confirm

List the resource in the target account and region. A stack deployed to staging but not production, or a table renamed in a migration, produces a genuine not-found while the configuration looks entirely reasonable.

4

The call is cross-account and the resource is elsewhere

How to confirm

Check the account number in the ARN against the function's account. Cross-account access needs both a resource policy allowing your role and the correct ARN; getting the ARN wrong produces not-found rather than denied.

5

IAM is returning not-found instead of denied

How to confirm

Confirm the resource exists in that account and region, then check the execution role. Some services deliberately return ResourceNotFoundException when the caller lacks permission to know the resource exists, so a resource you can see and the function cannot is a permissions question.

Fixes

Fix 1

Log the resolved identifier alongside the failure

The fastest fix is making the error self-explanatory. Logging the region, the account and the name the function actually used turns "not found" into "not found — because we looked in us-west-2".

jsconsole.log("config", {
  region: process.env.AWS_REGION,
  table: process.env.TABLE_NAME,
  function: process.env.AWS_LAMBDA_FUNCTION_NAME
});
Fix 2

Fail at startup when required configuration is missing

An unset environment variable should stop the function with a message naming the variable, not produce a lookup for an empty resource name several frames later. Checking at module scope makes it a clear init failure instead.

jsfunction required(name) {
  const value = process.env[name];
  if (!value) throw new Error(`${name} is not set`);
  return value;
}

// Module scope: fails once, loudly, rather than per request and obscurely.
const TABLE_NAME = required("TABLE_NAME");
Fix 3

Pass resource identifiers from the stack rather than typing them

Referencing the resource in the template means the name, region and account are always right and always move together with the deployment.

yamlResources:
  OrdersFunction:
    Type: AWS::Serverless::Function
    Properties:
      Environment:
        Variables:
          TABLE_NAME: !Ref OrdersTable
          QUEUE_URL: !Ref OrderQueue
Fix 4

Set the region explicitly when the target is not the function's own

An SDK client defaults to the function's region. When the resource genuinely lives elsewhere, say so at the client rather than relying on an ambient default.

jsconst client = new DynamoDBClient({ region: process.env.TABLE_REGION ?? process.env.AWS_REGION });

Also seen as

The same underlying failure, worded differently by a different runtime, SDK version, or logging layer. All of these land here — there is no separate page for each phrasing.

ResourceNotFoundException: Requested resource not found: Table: orders not foundResourceNotFoundException: Function not found: arn:aws:lambda:us-east-1:111122223333:function:workerThe specified log group does not existSecrets Manager can't find the specified secretlambda resourcenotfoundexception

Errors that show up alongside this one, or that people mistake for it.

References

LogStitch finds this automatically, across every invocation in your account.

Paste a log excerpt into the free web stitcher and see it grouped, classified, and measured in your browser — nothing is uploaded. Or run the Mac app against your own AWS profiles and get the same view over every function you own.