Michael Gaylord
Michael Gaylord

Reputation: 7312

Offline DynamoDB + Serverless + Lambda ResourceNotFoundException

I am trying to put together a really simple AWS Lambda using Serverless and DynamoDB.

My code to create an item is:

    dynamoDb: DocumentClient

    constructor() {
        this.dynamoDb = new DynamoDB.DocumentClient({region: 'us-east-1'})
    }

    saveFiles(files: File[]): Promise<boolean> {
        return new Promise<boolean>((resolve, reject ) => {
            files.forEach(file => {
                const tableName = process.env.DYNAMODB_TABLE
                this.dynamoDb.put({
                    TableName: tableName,
                    Item: {
                        downloaded: {N : `${file.downloaded ? 1 : 0}`},
                        location: {S: `${file.location}`}
                    }
                }, (error, result) => {
                    if (!!error) {
                        reject(error)
                        return
                    }
                    console.debug(`DB Save result: ${JSON.stringify(result)}`)
                    resolve(true)
                })
            })
        })
    }

The error is:

handler.ts:41
code:"ResourceNotFoundException"
message:"Requested resource not found"
name:"ResourceNotFoundException"
requestId:"2ST4DCE3NJ85UE32OAD6PUMTBJVV4KQNSO5AEMVJF66Q9ASUAAJG"
retryable:false
retryDelay:23.64284067311807
stack:"ResourceNotFoundException: Requested resource not found\n    at Request.extractError (/Users/michael/Development/javascript/data-export-lambda/.webpack/service/webpack:/node_modules/aws-sdk/lib/protocol/json.js:51:1)\n    at Request.callListeners (/Users/michael/Development/javascript/data-export-lambda/.webpack/service/webpack:/node_modules/aws-sdk/lib/sequential_executor.js:106:1)\n    at Request.emit (/Users/michael/Development/javascript/data-export-lambda/.webpack/service/webpack:/node_modules/aws-sdk/lib/sequential_executor.js:78:1)\n    at Request.emit (/Users/michael/Development/javascript/data-export-lambda/.webpack/service/webpack:/node_modules/aws-sdk/lib/request.js:683:1)\n    at Request.transition (/Users/michael/Development/javascript/data-export-lambda/.webpack/service/webpack:/node_modules/aws-sdk/lib/request.js:22:1)\n    at AcceptorStateMachine.runTo (/Users/michael/Development/javascript/data-export-lambda/.webpack/service/webpack:/node_modules/aws-sdk/lib/state_machine.js:14:1)\n    at /Users/mi...
statusCode:400

When I query DynamoDB to list my tables I get:

aws dynamodb list-tables --endpoint-url http://localhost:8000
{
    "TableNames": [
        "data-export-scheduler-dev"
    ]
}

Table names definitely match:

enter image description here

My serverless.yaml is:

service:
  name: data-export-scheduler

# Add the serverless-webpack plugin
plugins:
  - serverless-webpack
  - serverless-dynamodb-local
  - serverless-offline

# serverless offline config
custom:
  serverless-offline:
      port: 4000
      babelOptions:
        presets: ["es2015"]
  dynamodb:
    stages:
      - dev
    start:
      migrate: true

provider:
  name: aws
  region: us-east-1
  runtime: nodejs8.10
  environment:
    DYNAMODB_TABLE: ${self:service}-${opt:stage, self:provider.stage}
  iamRoleStatements:
    - Effect: Allow
      Action:
        - dynamodb:Query
        - dynamodb:Scan
        - dynamodb:GetItem
        - dynamodb:PutItem
        - dynamodb:UpdateItem
        - dynamodb:DeleteItem
      Resource: "arn:aws:dynamodb:${opt:region, self:provider.region}:*:table/${self:provider.environment.DYNAMODB_TABLE}"

functions:
  exportAPI:
    handler: handler.exportAPI
    events:
      - http:
          method: post
          path: export

resources:
  Resources:
    ExportDB:
      Type: 'AWS::DynamoDB::Table'
      DeletionPolicy: Retain
      Properties:
        AttributeDefinitions:
          - AttributeName: location
            AttributeType: S
        KeySchema:
          - AttributeName: location
            KeyType: HASH
        ProvisionedThroughput:
          ReadCapacityUnits: 1
          WriteCapacityUnits: 1
        TableName: ${self:provider.environment.DYNAMODB_TABLE}

Does anyone know what I could be doing wrong? The tables is there and I can query it from the DynamoDB CLI, but I keep getting the ResourceNotFoundException when trying to query it from the code.

Update 1: When I run a query from the CLI I get the same error:

aws dynamodb query --table-name data-export-scheduler-dev --key-condition-expression "downloaded = :v1" --expression-attribute-values '{":v1": { "S" : "0"}}' $LOCAL

An error occurred (ResourceNotFoundException) when calling the Query operation: Requested resource not found

Upvotes: 2

Views: 4577

Answers (1)

Thales Minussi
Thales Minussi

Reputation: 7215

By default, the AWS SDK looks up for resources in the Cloud. Therefore, when trying to connect to your DynamoDB instance, it is trying to connect to a DynamoDB table called data-export-scheduler-dev located in us-east-1 as per your configuration.

You have to tell the SDK to look for a local DynamoDB instance, by defining the endpoint attribute in its constructor.

Change:

constructor() {
    this.dynamoDb = new DynamoDB.DocumentClient({region: 'us-east-1'})
}

to

constructor() {
    this.dynamoDb = new DynamoDB.DocumentClient({region: 'us-east-1', endpoint: 'http://localhost:8000'})
}

Upvotes: 10

Related Questions