# Diagnose Netlify serverless function failures: timeouts, 502s, and bundling errors
Use this when a request to `/.netlify/functions/[name]` fails. Classify from
the *client-facing symptom plus the function logs* (Site → Functions →
function name → logs) before changing code — timeouts, crashes, and bundling
problems look identical from the browser.
## 1. Read the logs; match one of these signatures
### A. `Task timed out after 10.02 seconds` → execution timeout
```
Feb 7, 07:06:00 PM: e85dcb5b 2023-02-08T03:06:10.894Z e85dcb5b-... Task timed out after 10.02 seconds
Feb 7, 07:06:10 PM: e85dcb5b Duration: 10016.68 ms Memory Usage: 278 MB Init Duration: 165.48 ms
```
The browser sees a **502**. Synchronous functions have a **10-second**
execution limit by default.
Fixes, in order of preference:
1. **Make the work fit.** Add `console.time` / `console.log` markers to find
where the time goes. The usual culprits are slow upstream APIs and
connections that keep the event loop alive — e.g. a database client that
never closes makes the handler "finish in milliseconds" yet hang until the
10-second timeout, exactly like the logs above.
2. **Raise the limit.** Netlify support can raise a site's (or account's)
synchronous timeout to a maximum of **26 seconds** — this needs a Pro plan
or above, and a new deploy for it to take effect.
3. **Move long work out of the request path.** Background functions run up to
**15 minutes**: invoke them at `/.netlify/functions/[name]-background`; the
caller gets a 202 immediately and the work runs asynchronously. Edge
functions are the other escape hatch for streaming or long-lived workloads.
### B. 502 / "Function invocation failed" with NO timeout in the logs → the code crashed
The function threw before it could return. Read the exception in the logs —
but the Netlify-specific suspects are bundling problems:
1. **Runtime file reads fail** (`ENOENT` on a JSON/template/data file): the
bundler only ships files it can statically trace. Declare extra files
explicitly:
```toml
[functions]
included_files = ["data/**"]
```
Globs support `!`-prefixed exclusions (e.g. `"!data/large/**"`).
2. **Native modules break under esbuild** (sharp, sqlite3, canvas, ...): they
can't be inlined into the bundle. Ship them as-is in `node_modules`
instead:
```toml
[functions]
external_node_modules = ["sharp"]
```
3. **Bundle too big or bundler misbehaving:** switch the bundler explicitly
and read the deploy log — it lists the largest files when a bundle is
oversized. The hard ceiling is **250 MB unzipped per function**:
```toml
[functions]
node_bundler = "esbuild"
```
(The bundler choices are `zisi`, `esbuild`, `esbuild_zisi`, and `nft`;
esbuild produces the smaller artifacts.)
### C. 404 at `/.netlify/functions/[name]` → the function was never deployed
Causes: the wrong functions directory (check `[functions] directory` or
`[build] functions` — both are relative to the base directory), the file
didn't match what the bundler expects, or a framework plugin wrote to a
different directory. Run `netlify build` locally and check which functions it
emits.
### D. Works locally, fails on Netlify
`netlify dev` serves functions with your local Node and your shell's
environment; production uses the configured bundler and the site's
environment variables. Two gotchas: env vars are injected at deploy time, so
a newly added variable needs a new deploy before the live function sees it;
and `netlify dev --context production` is the closest local approximation.
## 2. Config reference
```toml
[functions]
directory = "netlify/functions" # where your function sources live
node_bundler = "esbuild" # zisi | esbuild | esbuild_zisi | nft
included_files = ["data/**"] # extra files to ship with the bundle
external_node_modules = ["sharp"] # modules shipped in node_modules, not inlined
```
## 3. Checklist
1. 502 + `Task timed out after 10.02 seconds` → fit the work under 10s, ask
support for 26s (Pro+), or go background (`-background`, 202, 15 min).
2. 502 without a timeout → read the exception; then `included_files`,
`external_node_modules`, `node_bundler`.
3. 404 → functions directory config (relative to base) and a local
`netlify build` to see what's emitted.
4. Bundle deploy failures → esbuild plus pruned `included_files`; 250 MB
unzipped is the ceiling.
5. New env var → new deploy; the live function won't see it otherwise.