Skip to content

Function-level vpc: false / vpc: null opt-out rejected by config validation in v4 (schema ↔ compile mismatch) #421

Description

@bburgalat-bcg

Summary

In v3, a function could opt out of the provider-level VPC with vpc: false (or vpc: null). In v4 this now fails hard at sls package / deploy:

Configuration error:
     at 'functions.<fn>.vpc': must be object

The function VPC compile logic still supports false / null, but the JSON schema rejects them. Because v4 flipped configValidationMode from warn (v3 default) to error (v4 default), this pre-existing schema/compile inconsistency is now a blocking error instead of a silent warning.

There is currently no schema-valid way to opt a single function out of provider.vpc under strict validation (false, null, and {} are all rejected — {} fails the required constraint).

Environment

  • osls: 4.0.0 (local)
  • node: 22.x
  • OS: Linux (CI) and Windows (local), same result

Minimal reproduction

serverless.yml:

service: repro-vpc-false
frameworkVersion: '4'

provider:
  name: aws
  runtime: nodejs22.x
  region: eu-west-1
  vpc:
    securityGroupIds: [sg-000000000000]
    subnetIds: [subnet-000000000000]

functions:
  inVpc:
    handler: handler.a
  noVpc:
    handler: handler.b
    vpc: false   # opt out of provider.vpc - worked in v3

Run:

npx sls package --stage dev

Actual:

Configuration error:
     at 'functions.noVpc.vpc': must be object

Expected: noVpc is created without a VpcConfig (opt-out honored), as in v3.

Root cause

The two layers disagree.

Compile logic — lib/plugins/aws/package/compile/functions.js still treats false / null as an explicit opt-out:

if (functionObject.vpc !== null && functionObject.vpc !== false) {
  if (!functionObject.vpc) functionObject.vpc = {};
  // ... build VpcConfig
}

Schema — awsLambdaVpcConfig in lib/plugins/aws/provider.js is strictly:

awsLambdaVpcConfig: {
  type: 'object',
  properties: { ipv6AllowedForDualStack: {}, securityGroupIds: {}, subnetIds: {} },
  additionalProperties: false,
  required: ['securityGroupIds', 'subnetIds'],
}

No anyOf allowing false or null.

So vpc: false was never schema-valid; it only worked in v3 because config validation defaulted to warn (the violation was an ignored warning while the compile logic did the right thing). v4's configValidationMode: error default promotes that warning to a hard error, removing the only per-function VPC opt-out mechanism.

This inconsistency is very likely inherited from Serverless Framework v3.

Suggested fix

Update the schema for function-level vpc to match the compile logic, e.g.:

vpc: {
  anyOf: [
    { $ref: '#/definitions/awsLambdaVpcConfig' },
    { const: false },
    { type: 'null' },
  ],
}

so vpc: false / vpc: null remain valid opt-outs under strict validation.

Workaround (for others hitting this)

Either:

  1. Set configValidationMode: warn (restores v3 behavior — the compile logic handles vpc: false correctly), or
  2. Remove provider.vpc and declare vpc only on the functions that need it (functions without vpc are simply not placed in a VPC).

Option 2 keeps strict validation but does not scale well for services with many functions that share the same VPC.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions