serverless: Cannot find module 'ajv/dist/compile/codegen'

Not sure if this is something that just can’t be helped, but it seems that if a NodeJS project has a dependency on ajv^6 it’ll cause the packaging step to fail. I believe this was caused by the bump to ajv^7. I know that many projects still depend on the earlier version, so it might break a lot of projects.

Steps to reproduce:

  1. Create a new project using sls init
  2. Select NodeJS project
  3. Install ajv^6 via npm i ajv@^6
  4. Execute sls package
serverless.yml
# Welcome to Serverless!
#
# This file is the main config file for your service.
# It's very minimal at this point and uses default values.
# You can always add more config options for more control.
# We've included some commented out config examples here.
# Just uncomment any of them to get that config option.
#
# For full config options, check the docs:
#    docs.serverless.com
#
# Happy Coding!

service: test
# app and org for use with dashboard.serverless.com
#app: your-app-name
#org: your-org-name

# You can pin your service to only deploy with a specific Serverless version
# Check out our docs for more details
frameworkVersion: '2'

provider:
  name: aws
  runtime: nodejs12.x

# you can overwrite defaults here
#  stage: dev
#  region: us-east-1

# you can add statements to the Lambda function's IAM Role here
#  iamRoleStatements:
#    - Effect: "Allow"
#      Action:
#        - "s3:ListBucket"
#      Resource: { "Fn::Join" : ["", ["arn:aws:s3:::", { "Ref" : "ServerlessDeploymentBucket" } ] ]  }
#    - Effect: "Allow"
#      Action:
#        - "s3:PutObject"
#      Resource:
#        Fn::Join:
#          - ""
#          - - "arn:aws:s3:::"
#            - "Ref" : "ServerlessDeploymentBucket"
#            - "/*"

# you can define service wide environment variables here
#  environment:
#    variable1: value1

# you can add packaging information here
#package:
#  include:
#    - include-me.js
#    - include-me-dir/**
#  exclude:
#    - exclude-me.js
#    - exclude-me-dir/**

functions:
  hello:
    handler: handler.hello
#    The following are a few example events you can configure
#    NOTE: Please make sure to change your handler code to work with those events
#    Check the event documentation for details
#    events:
#      - http:
#          path: users/create
#          method: get
#      - websocket: $connect
#      - s3: ${env:BUCKET}
#      - schedule: rate(10 minutes)
#      - sns: greeter-topic
#      - stream: arn:aws:dynamodb:region:XXXXXX:table/foo/stream/1970-01-01T00:00:00.000
#      - alexaSkill: amzn1.ask.skill.xx-xx-xx-xx
#      - alexaSmartHome: amzn1.ask.skill.xx-xx-xx-xx
#      - iot:
#          sql: "SELECT * FROM 'some_topic'"
#      - cloudwatchEvent:
#          event:
#            source:
#              - "aws.ec2"
#            detail-type:
#              - "EC2 Instance State-change Notification"
#            detail:
#              state:
#                - pending
#      - cloudwatchLog: '/aws/lambda/hello'
#      - cognitoUserPool:
#          pool: MyUserPool
#          trigger: PreSignUp
#      - alb:
#          listenerArn: arn:aws:elasticloadbalancing:us-east-1:XXXXXX:listener/app/my-load-balancer/50dc6c495c0c9188/
#          priority: 1
#          conditions:
#            host: example.com
#            path: /hello

#    Define function environment variables here
#    environment:
#      variable2: value2

# you can add CloudFormation resource templates here
#resources:
#  Resources:
#    NewResource:
#      Type: AWS::S3::Bucket
#      Properties:
#        BucketName: my-new-bucket
#  Outputs:
#     NewOutput:
#       Description: "Description for the output"
#       Value: "Some output value"
sls package output
Serverless: Running "serverless" installed locally (in service node_modules)
 
  Error --------------------------------------------------
 
  Error: Cannot find module 'ajv/dist/compile/codegen'
  Require stack:
  - /tmp/test/node_modules/ajv-keywords/dist/definitions/typeof.js
  - /tmp/test/node_modules/ajv-keywords/dist/keywords/typeof.js
  - /tmp/test/node_modules/ajv-keywords/dist/keywords/index.js
  - /tmp/test/node_modules/ajv-keywords/dist/index.js
  - /tmp/test/node_modules/serverless/lib/classes/ConfigSchemaHandler/index.js
  - /tmp/test/node_modules/serverless/lib/Serverless.js
  - /usr/local/lib/node_modules/serverless/lib/Serverless.js
  - /usr/local/lib/node_modules/serverless/scripts/serverless.js
  - /usr/local/lib/node_modules/serverless/bin/serverless.js
      at Function.Module._resolveFilename (internal/modules/cjs/loader.js:957:15)
      at Function.Module._load (internal/modules/cjs/loader.js:840:27)
      at Module.require (internal/modules/cjs/loader.js:1019:19)
      at require (internal/modules/cjs/helpers.js:77:18)
      at Object.<anonymous> (/tmp/test/node_modules/ajv-keywords/src/definitions/typeof.ts:2:1)
      at Module._compile (internal/modules/cjs/loader.js:1133:30)
      at Object.Module._extensions..js (internal/modules/cjs/loader.js:1153:10)
      at Module.load (internal/modules/cjs/loader.js:977:32)
      at Function.Module._load (internal/modules/cjs/loader.js:877:14)
      at Module.require (internal/modules/cjs/loader.js:1019:19)
      at require (internal/modules/cjs/helpers.js:77:18)
      at Object.<anonymous> (/tmp/test/node_modules/ajv-keywords/src/keywords/typeof.ts:2:1)
      at Module._compile (internal/modules/cjs/loader.js:1133:30)
      at Object.Module._extensions..js (internal/modules/cjs/loader.js:1153:10)
      at Module.load (internal/modules/cjs/loader.js:977:32)
      at Function.Module._load (internal/modules/cjs/loader.js:877:14)
      at Module.require (internal/modules/cjs/loader.js:1019:19)
      at require (internal/modules/cjs/helpers.js:77:18)
      at Object.<anonymous> (/tmp/test/node_modules/ajv-keywords/src/keywords/index.ts:2:1)
      at Module._compile (internal/modules/cjs/loader.js:1133:30)
      at Object.Module._extensions..js (internal/modules/cjs/loader.js:1153:10)
      at Module.load (internal/modules/cjs/loader.js:977:32)
      at Function.Module._load (internal/modules/cjs/loader.js:877:14)
      at Module.require (internal/modules/cjs/loader.js:1019:19)
      at require (internal/modules/cjs/helpers.js:77:18)
      at Object.<anonymous> (/tmp/test/node_modules/ajv-keywords/src/index.ts:3:1)
      at Module._compile (internal/modules/cjs/loader.js:1133:30)
      at Object.Module._extensions..js (internal/modules/cjs/loader.js:1153:10)
      at Module.load (internal/modules/cjs/loader.js:977:32)
      at Function.Module._load (internal/modules/cjs/loader.js:877:14)
      at Module.require (internal/modules/cjs/loader.js:1019:19)
      at require (internal/modules/cjs/helpers.js:77:18)
      at ConfigSchemaHandler.validateConfig (/tmp/test/node_modules/serverless/lib/classes/ConfigSchemaHandler/index.js:102:5)
      at Service.validate (/tmp/test/node_modules/serverless/lib/classes/Service.js:222:41)
      at /tmp/test/node_modules/serverless/lib/Serverless.js:200:49
      at tryCatcher (/tmp/test/node_modules/bluebird/js/release/util.js:16:23)
      at Promise._settlePromiseFromHandler (/tmp/test/node_modules/bluebird/js/release/promise.js:547:31)
      at Promise._settlePromise (/tmp/test/node_modules/bluebird/js/release/promise.js:604:18)
      at Promise._settlePromise0 (/tmp/test/node_modules/bluebird/js/release/promise.js:649:10)
      at Promise._settlePromises (/tmp/test/node_modules/bluebird/js/release/promise.js:729:18)
      at _drainQueueStep (/tmp/test/node_modules/bluebird/js/release/async.js:93:12)
      at _drainQueue (/tmp/test/node_modules/bluebird/js/release/async.js:86:9)
      at Async._drainQueues (/tmp/test/node_modules/bluebird/js/release/async.js:102:5)
      at Immediate.Async.drainQueues [as _onImmediate] (/tmp/test/node_modules/bluebird/js/release/async.js:15:14)
      at processImmediate (internal/timers.js:456:21)
      at process.topLevelDomainCallback (domain.js:137:15)
 
     For debugging logs, run again after setting the "SLS_DEBUG=*" environment variable.
 
  Get Support --------------------------------------------
     Docs:          docs.serverless.com
     Bugs:          github.com/serverless/serverless/issues
     Issues:        forum.serverless.com
 
  Your Environment Information ---------------------------
     Operating System:          linux
     Node Version:              12.16.3
     Framework Version:         2.11.1 (local)
     Plugin Version:            4.1.2
     SDK Version:               2.3.2
     Components Version:        3.3.0

Installed version

Serverless: Running "serverless" installed locally (in service node_modules)
Framework Core: 2.18.0 (local)
Plugin: 4.4.2
SDK: 2.3.2
Components: 3.4.6

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 9
  • Comments: 30 (14 by maintainers)

Commits related to this issue

Most upvoted comments

I was facing the same issue with, I temporarily solved it by installing ajv@7.0.3 and now it’s added as dependency on my package.json:

  ...
  "devDependencies": {
    "serverless-step-functions": "^2.27.1"
  },
  "dependencies": {
    "ajv": "^7.0.3",
    "serverless": "^2.18.0",
    "serverless-pseudo-parameters": "^2.5.0",
    "serverless-python-requirements": "^5.1.0"
  }

It’s just a “workaround” for those who need to deploy their applications, and problably will be fixed asap. By the way I’m running the serverless v2.18.0, npm v6.14.10 and node v10.19.0.

I think there is something funny about version 2.18.0 of serverless. 3 separate users have posted here that they have run into the error Cannot find module 'ajv/dist/compile/codegen' since upgrading to 2.18.0, and they didn’t have any errors with 2.17.0. Also, in the example I described in an earlier post, upgrading to 2.18.0 caused the error in one project but not in the other. If this were a straight up bug in npm v6, wouldn’t both of them fail?

My projects don’t have a direct dependency on ajv either.

AJV will be reverted to v6 starting with next release of Framework, it’s due to performance issues with observed which appear to not be easily fixable, for more info check:

This means that this problem will be fixed for you, unless you’ve upgraded your services to rely on AJV v7, as then you’ll face the same problem with same installer when serverless depends on AJV v6

Seeing as npm v6 is the current LTS version, and npm v7 is the development release, I believe serverless should not break under npm v6 just because the project where it is used happens to have ajv 6 as a dependency. Especially considering that the previous minor release does not break in this scenario.

That’s assuming I understand the problem correctly.

Is there not a way the change to serverless that broke this scenario could be modified so that it does not break in these circumstances?

npm v7 auto installs peer dependencies, whereas npm v6 does not. It might be this feature that makes it work under npm v7, rather than a bug fix for some behaviour in npm v6?

I’m seeing this issue - we’ve had to specify 2.17.0 in order for our deploys to work.

I should add - we don’t have a direct dependency on ajv, but we’re using other packages that likely have dependencies on ajv.

I think @medikoo is correct that this issue has been caused by serverless version 2.18.0 upgrading its dependencies. Specifically, I think it’s the upgrade of ajv-keywords to version ^4.0.0 that’s brought this problem to the surface - that’s the package that has the peer dependency on ajv version ^7.0.3.

This looks to be an example of a bug in npm that’s been around for a long time. That issue is almost 2 years old and was never resolved by the look of things. It might have been resolved by npm version 7, but I can’t find confirmation of that anywhere. The person who raised that issue did a great job of reproducing the problem, and you can see that the circumstances in their demo project are very similar to the case that we’re seeing here. Just replace webpack in their example with serverless in ours and it looks like the very same situation.

In which case, I suppose the options are to do one of the following:

@medikoo - we are currently getting around this issue by pinning our dev dependency on serverless at v.2.17.0, so the problem does not exist there.

Note that we do not have any direct dependency on ajv - but rather another package we are using has it as a dependency.

But it might be that with npm v6 support for peer dependencies was just informative, and in light of that, it’s no wonder it cannot handle such setup properly.

@lewgordon workaround on your side could be to define ajv-keywords@3 dependency aside ajv@6. It’ll ensure that ajv-keywords@4 will get installed in serverless/node_modules

@lewgordon I’ve just tested it locally, and indeed it happens with npm v6, but not with npm v7 which installs project as expected

It’s a clear bug in npm v6 (it’s probably unlikely they’ll fix it in that branch)