serverless/serverless · error · ServerlessError
INVOKE_LOCAL_UNSUPPORTED_ENV_VARIABLE
INVOKE_LOCAL_UNSUPPORTED_ENV_VARIABLE
Error message
Unsupported environment variable format: ${inspect(value)} What it means
Thrown by invoke-local's environment resolver when an env-var value is an object (a CloudFormation intrinsic) but uses a key other than Fn::ImportValue or Ref. The local resolver only knows those two intrinsics; anything else (Fn::Sub, Fn::Join, Fn::GetAtt, etc.) is unsupported for local invocation.
Source
Thrown at packages/serverless/lib/plugins/aws/invoke-local/index.js:285
}
async resolveConfiguredEnvVars(configuredEnvVars) {
await Promise.all(
Object.entries(configuredEnvVars).map(async ([name, value]) => {
if (!_.isObject(value)) return
try {
if (value['Fn::ImportValue']) {
configuredEnvVars[name] = await resolveCfImportValue(
this.provider,
value['Fn::ImportValue'],
)
} else if (value.Ref) {
configuredEnvVars[name] = await resolveCfRefValue(
this.provider,
value.Ref,
)
} else {
throw new ServerlessError(
`Unsupported environment variable format: ${inspect(value)}`,
'INVOKE_LOCAL_UNSUPPORTED_ENV_VARIABLE',
)
}
} catch (error) {
throw new ServerlessError(
`Could not resolve "${name}" environment variable: ${error.message}`,
'INVOKE_LOCAL_INVALID_ENV_VARIABLE',
)
}
}),
)
return configuredEnvVars
}
async loadEnvVars() {
const lambdaName = this.options.functionObj.nameView on GitHub (pinned to b9d7ea51c8)
Solutions
- Replace the unsupported intrinsic with Fn::ImportValue or Ref if the underlying value can be expressed that way.
- Use a literal string for the value when invoking locally.
- Resolve the composed value out-of-band and pass it via a local-only environment file/variable.
Example fix
# before
environment:
TOPIC_ARN:
Fn::Sub: 'arn:aws:sns:${AWS::Region}:${AWS::AccountId}:my-topic'
# after (resolvable locally)
environment:
TOPIC_ARN:
Ref: MyTopicParameter Defensive patterns
Strategy: type-guard
Validate before calling
const SUPPORTED = ['Fn::ImportValue', 'Ref']
function isResolvableEnvValue(v) {
if (v == null || typeof v !== 'object') return true
return SUPPORTED.some((k) => k in v)
}
for (const [k, v] of Object.entries(mergedEnv)) {
if (!isResolvableEnvValue(v)) throw new Error(`env ${k} uses an unsupported intrinsic for local invoke`)
} Type guard
function isLocallyResolvableIntrinsic(v) {
return v == null || typeof v !== 'object' || 'Fn::ImportValue' in v || 'Ref' in v
} Prevention
- Restrict environment intrinsics to Fn::ImportValue/Ref when local invoke is needed.
- Move complex intrinsic composition out of environment values and into resolved parameters.
- Maintain a local-only env override file for values that cannot be expressed as Ref/ImportValue.
When it happens
Trigger: Setting provider.environment or function.environment entries to `{ 'Fn::Sub': '...' }`, `{ 'Fn::Join': [...] }`, `{ 'Fn::GetAtt': [...] }`, or any intrinsic besides ImportValue/Ref, then running `sls invoke local`.
Common situations: Using Fn::Sub/Fn::Join in environment values (valid at deploy time, but the local invoker cannot resolve them); migrating config that relied on intrinsic composition.
Related errors
- Custom priority not yet implemented.
- CLOUDFORMATION_STACK_RESOURCE_NOT_FOUND
- CLOUDFORMATION_API_ID_NOT_FOUND
- CLOUDFORMATION_DESCRIBE_STACK_FAILED
- UNABLE_TO_RESOLVE_HTTP_API_ID
AI-assisted analysis of serverless/serverless@b9d7ea51c8 (2026-08-13).
Data as JSON: /api/errors/9a2887a15766f68b.
Report an issue: GitHub.