serverless/serverless · error · ServerlessError
ESBULD_BUILD_ERROR
ESBULD_BUILD_ERROR
Error message
${err.message} What it means
Generic wrapper for esbuild's own build failures: when the build step throws and the error is not already a ServerlessError raised deliberately by the plugin (output collision, outExtension mismatch, etc.), it is re-wrapped with code ESBULD_BUILD_ERROR keeping the original message. Read err.message — it is esbuild's underlying diagnostic.
Source
Thrown at packages/serverless/lib/plugins/esbuild/index.js:1072
}
try {
await this._buildProject(
functionsToBuild,
handlerPropertyName,
buildProperties,
)
} catch (err) {
if (this.serverless.devmodeEnabled === true) {
return
}
// Errors this path raises deliberately (an output collision, an
// unusable `outExtension`) already say what to do about them; only
// esbuild's own failures need wrapping.
if (err instanceof ServerlessError) {
throw err
}
throw new ServerlessError(err.message, 'ESBULD_BUILD_ERROR')
}
if (handlerPropertyName !== 'originalHandler') {
this._assertAllHandlersBuilt(functionsToBuild, handlerPropertyName)
}
return
}
const outputExtension = this._outputExtension(buildProperties)
// Multiple functions can share a single handler file (e.g. one module
// exporting several handlers). Building each function separately would
// spawn concurrent esbuild.build() calls writing to the same outfile,
// racing on truncate+write and corrupting the output (#13716). Instead we
// group functions by their resolved absolute entry path and build each
// unique file once, applying the per-function side effects to every alias
// in the group afterwards.View on GitHub (pinned to ba6ba66c01)
Solutions
- Read err.message for esbuild's actual diagnostic and fix the source/import it names
- Run esbuild or tsc directly on the file to reproduce the error faster
- Verify tsconfig and build.esbuild options (target, loaders, plugins) are valid
- If a plugin you added throws, fix or remove that plugin
Example fix
// before
import { foo } from './nonexistent'
// after
import { foo } from './utils' Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check: compile the entry points with esbuild directly to surface diagnostics early
import { build } from 'esbuild'
await build({ entryPoints: ['src/handler.ts'], bundle: true, write: false, logLevel: 'silent' }) Try / catch
try {
await deploy()
} catch (e) {
if (e.code === 'ESBULD_BUILD_ERROR') {
// e.message is esbuild's own diagnostic; surface it verbatim
console.error('esbuild failed:', e.message)
}
throw e
} Prevention
- Run tsc --noEmit or esbuild locally before deploying
- Keep imports valid and committed; avoid missing modules in CI
- Pin esbuild config (target, loaders, tsconfig) and validate after changes
- Read err.message first — it is the raw esbuild diagnostic, not a generic failure
When it happens
Trigger: Any esbuild compilation failure during _buildProject: syntax errors, unresolved imports, invalid loader/plugin errors, tsconfig problems — anything esbuild itself rejects.
Common situations: TypeScript type/syntax errors, importing a missing module, a bad tsconfig path, unsupported syntax for the target runtime.
Related errors
- PLUGIN_TYPESCRIPT_CONFLICT
- ESBUILD_OUTPUT_COLLISION
- ESBUILD_BUILD_DIR_RESET_FAILED
- ESBUILD_TSCONFIG_NOT_FOUND
- ESBUILD_TSCONFIG_INVALID
AI-assisted analysis of serverless/serverless@ba6ba66c01 (2026-09-13).
Data as JSON: /api/errors/e3b455f1bf146d0f.
Report an issue: GitHub.