serverless/serverless · error · ServerlessError
EXTERNAL_HTTP_API_CORS_CONFIG
EXTERNAL_HTTP_API_CORS_CONFIG
Error message
Cannot setup CORS rules for externally configured HTTP API
What it means
Thrown by the HTTP API (API Gateway v2) event plugin during configuration resolution. provider.httpApi.id marks the API as externally managed (created outside this stack), so the framework cannot attach or modify CORS settings on it. Setting provider.httpApi.cors alongside provider.httpApi.id is therefore rejected. CORS must be configured on the external API directly (AWS console, separate stack, or CDK).
Source
Thrown at packages/serverless/lib/plugins/aws/package/compile/events/http-api.js:456
Object.defineProperties(
HttpApiEvents.prototype,
memoizeeMethods({
resolveConfiguration: d(function () {
const routes = new Map()
const providerConfig = this.serverless.service.provider
const userConfig = providerConfig.httpApi || {}
this.config = {
routes,
id: userConfig.id,
metrics: userConfig.metrics || false,
disableDefaultEndpoint: userConfig.disableDefaultEndpoint,
}
let cors = null
let shouldFillCorsMethods = false
const userCors = userConfig.cors
if (userCors) {
if (userConfig.id) {
throw new ServerlessError(
'Cannot setup CORS rules for externally configured HTTP API',
'EXTERNAL_HTTP_API_CORS_CONFIG',
)
}
cors = this.config.cors = {}
if (userConfig.cors === true) {
Object.assign(cors, defaultCors)
shouldFillCorsMethods = true
} else {
cors.allowedOrigins = userCors.allowedOrigins
? toSet(userCors.allowedOrigins)
: defaultCors.allowedOrigins
cors.allowedHeaders = userCors.allowedHeaders
? toSet(userCors.allowedHeaders)
: defaultCors.allowedHeaders
if (userCors.allowedMethods)
cors.allowedMethods = toSet(userCors.allowedMethods)
else shouldFillCorsMethods = trueView on GitHub (pinned to b9d7ea51c8)
Solutions
- Remove the provider.httpApi.cors block from serverless.yml and configure CORS on the external HTTP API in its owning stack/CDK/Console.
- If you want the framework to manage CORS, remove provider.httpApi.id so the API is created in this stack.
- Double-check no computed value (variable/resolver) is silently producing a truthy cors when id is also set.
Example fix
# before
provider:
httpApi:
id: abc123xyz
cors: true
# after
provider:
httpApi:
id: abc123xyz
# (configure CORS on the external API itself) Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight check before deploy/package
import { readFileSync } from 'fs'
const cfg = require('js-yaml').load(readFileSync('serverless.yml','utf8'))
const h = cfg.provider?.httpApi ?? {}
if (h.id && h.cors !== undefined) {
throw new Error('EXTERNAL_HTTP_API_CORS_CONFIG: remove httpApi.cors when httpApi.id is set')
} Type guard
// True when the API is externally managed and CORS must NOT be set const isExternalHttpApiWithCorsConflict = (httpApi) => Boolean(httpApi?.id) && httpApi?.cors !== undefined && httpApi?.cors !== null
Prevention
- Treat provider.httpApi.id as 'import-only': never pair it with cors/authorizers/logs blocks.
- Run `sls print` after merging cross-stack configs to confirm no stray httpApi sub-keys remain.
- Keep shared-API config in one place; consumers should only reference id.
When it happens
Trigger: In serverless.yml, provider.httpApi.id is set to a string/CFN reference (e.g. an existing API ID) AND provider.httpApi.cors is truthy (either true, or an object with allowedOrigins etc.). The resolveConfiguration hook runs during package:compileEvents and the very first cors branch throws.
Common situations: Migrating an HTTP API to be externally managed (importing an existing API) while leaving the previously-working cors block in place. Copying a service config snippet that includes cors without noticing the id field is set. Splitting a monolith into a shared-API stack + function stacks.
Related errors
- EXTERNAL_HTTP_API_AUTHORIZERS_CONFIG
- EXTERNAL_HTTP_API_LOGS_CONFIG
- EXTERNAL_HTTP_API_AUTHORIZER_WITHOUT_EXTERNAL_HTTP_API
- HTTP_API_CUSTOM_AUTHORIZER_NEITHER_FUNCTION_ARN_NOR_FUNCTION_NAME_DEFINED
- HTTP_API_CUSTOM_AUTHORIZER_BOTH_FUNCTION_ARN_AND_FUNCTION_NAME_DEFINED
AI-assisted analysis of serverless/serverless@b9d7ea51c8 (2026-08-13).
Data as JSON: /api/errors/f9d031894a5d9211.
Report an issue: GitHub.