Build failed: find the line that matters, then fix the cause.
The line that explains a failed build is rarely the last one. Find the step that failed (install, build or release), skip the warnings, and read the first real error above the exit line. Most failures come from a stale lockfile, the wrong root directory, a missing environment variable, a native module or running out of memory.
Facts checked
How to read a failed build log
- Find the step. A deploy installs dependencies, builds, runs a release command if you set one, then starts the app. On Canner the summary names the step:
install failed (exit 1)orbuild failed (exit 1), followed by the error lines it picked out. - Skip the warnings.
npm warn deprecated …lines and bundle-size warnings don’t fail a build. Canner’s summary drops lines marked as warnings for that reason. - Read upward from the end. The last lines are usually the tool reporting that it exited. The cause is the first
Error:,npm error,✘ [ERROR]orType error:above them. - Note the exit code. It tells you whether the tool failed on its own or was stopped from outside (table below).
| Exit code | Meaning | Usual cause in a build |
|---|---|---|
| 1 † | The command reported an error and exited | Anything: read the error lines |
| 134 † | 128 + 6: the process aborted (SIGABRT) | Node hit its heap limit: JavaScript heap out of memory |
| 137 † | 128 + 9: the process was killed (SIGKILL) | The build used more memory than its container allows |
† Competitor details come from each vendor’s own published pages on the dates shown; prices and plans change, so check the vendor before you decide. 1 (2026-10-29) · 134 (2026-10-29) · 137 (2026-10-29)
The common causes, with the exact message
These are the messages Canner prints, and the tool messages it recognizes. On a failed deployment, Canner shows a How to fix it card for the cause it found, with the raw log one click away under Error details.
| The log says | What happened | Fix |
|---|---|---|
A lockfile is required to deploy † | No package-lock.json, pnpm-lock.yaml, yarn.lock or bun.lockb was committed | Run your package manager’s install locally and commit the lockfile |
npm ci can only install packages when your package.json and package-lock.json or npm-shrinkwrap.json are in sync, ERR_PNPM_OUTDATED_LOCKFILE, or Canner’s Your lockfile is out of sync with the manifest † | package.json changed without reinstalling | Run npm install (or pnpm install) locally, commit the updated lockfile, push |
ERR_PNPM_LOCKFILE_BREAKING_CHANGE, or Yarn’s This project is configured to use yarn | The lockfile was written by another pnpm or Yarn major | Pin it: "packageManager": "pnpm@<version>" in package.json. The log then shows [canner] using pnpm … (pinned by packageManager in package.json) |
This repo holds a pnpm workspace, but the root itself has nothing to deploy. Found web, api. | A monorepo, built from its root | Set Root directory to the app, or make one Canner project per app from the same repository |
No package.json or index.html found. or Could not detect a supported project | Nothing at the root looks like an app; often an upload zipped one folder too deep | Check Root directory; re-zip so package.json sits at the top of the archive |
package.json engines.node=">=26" needs a Node version Canner doesn't offer (available: 24, 22). | engines.node excludes every Node version on the platform | Widen or remove engines.node. A range that just excludes the project’s default picks the newest one that fits, and the log says which |
[canner] ⚠ Native modules need a postinstall allowlist (sharp), then Could not locate the bindings file or NODE_MODULE_VERSION | Install scripts are off by default, so a native binary was never built | Allow that package’s install script (code below) |
Missing environment variable: RESEND_API_KEY (card), from errors like supabaseUrl is required or Environment variable not found: DATABASE_URL | The build reads a value the project doesn’t have | Add it. The card offers a field for each named variable and Save and retry. For DATABASE_URL, create a database: Canner sets it |
Errors from prisma migrate deploy or drizzle-kit migrate during the build | A migration runs in the build command | Move it to the release command (Settings → Build) |
Module not found: Can't resolve './components/Header' | The package isn’t installed, or the import’s case doesn’t match the file: macOS and Windows forgive that, Linux doesn’t | Add the dependency, or fix the path’s capitalization |
build ran out of memory and was killed. or JavaScript heap out of memory † | The build passed its memory budget | See JavaScript heap out of memory. For Next.js, type checking is the usual peak |
The command stopped at a prompt that needs an answer: “…” | A command asked a yes/no question nobody was there to answer | Use its non-interactive flag (--yes, --force) or pipe the answer: printf 'y' | your-command |
† Competitor details come from each vendor’s own published pages on the dates shown; prices and plans change, so check the vendor before you decide. `A lockfile is required to deploy` (2026-10-29) · `npm ci can only install packages when your package.json and package-lock.json or npm-shrinkwrap.json are in sync`, `ERR_PNPM_OUTDATED_LOCKFILE`, or Canner’s `Your lockfile is out of sync with the manifest` (2026-10-29) · `build ran out of memory and was killed.` or `JavaScript heap out of memory` (2026-10-29)
Native modules: the failure that shows up later
Canner installs dependencies with install scripts disabled, for supply-chain safety. Most packages don’t need one. Packages that compile or download a native binary (sharp, bcrypt, better-sqlite3, canvas) install without error and then fail when your code first imports them, which can be at runtime rather than in the build.
The build log warns you before that happens, naming the packages. Allow them in package.json; Canner then rebuilds just those, with network access blocked:
// package.json: let these packages run their install script
{
"canner": { "allowedBuildScripts": ["sharp", "better-sqlite3"] }
}
// pnpm projects can use pnpm's own setting instead
{
"pnpm": { "onlyBuiltDependencies": ["sharp", "better-sqlite3"] }
}Commands that wait for an answer
A deploy runs unattended. When a command prints something like Would you like to proceed? (y/N) and then goes quiet for about 20 seconds, Canner treats it as stuck at a question. For the release command, the deploy page shows the question and, where answers are turned on, offers Yes and No; with nobody there it stops after 5 minutes and tells you what was asked. The deploys docs list the usual flags: --force for prisma migrate reset and artisan migrate, --accept-data-loss for prisma db push, --noinput for Django’s collectstatic.
When the build passes but the deploy fails
A build that succeeds still has to start. The new version must answer on / (or your health-check path) within 30 seconds. app did not respond on / within 30s almost always means the app listens on a hard-coded port instead of process.env.PORT, or crashed on boot over a missing variable. The failure message includes the end of your app’s own log, which usually holds the stack trace. A bot or job runner with no web server should be redeployed as a worker, which skips the check. The troubleshooting docs cover each case.
A failed release command stops the deploy before the new version starts, so the version already live keeps running.
Reproduce it before you push again
“Works on my machine” builds usually differ in one of four ways: files that aren’t committed, a lockfile that isn’t current, a case-insensitive file system, or a different Node version. A clean Linux container rules out all four:
# Reproduce a clean Linux build on your machine
docker run --rm -it -v "$PWD":/app -w /app node:22 \
sh -c "npm ci && NODE_ENV=production npm run build"Let your agent read the log
If you work with Claude Code or Cursor, Canner’s MCP server gives the agent canner_get_deployment, which returns a deployment in full, build log included. It can read the failure, fix the code and redeploy without you copying logs around. More guides are under hosting by framework.
Questions
Why does my build work locally but fail on deploy?
Usually an uncommitted file (often .env or the lockfile), a lockfile out of sync with package.json, an import whose capitalization only works on macOS or Windows, or a different Node version. Building in a clean Linux container reproduces most of these.
What does exit code 1 mean in a build log?
Only that the command reported an error. The cause is in the error lines above it. Exit 134 and 137 are different: the process was aborted or killed, usually over memory.
Does Canner retry a failed build?
Retry on the deployment re-runs the same commit or upload, which helps after you fix a variable or when a registry hiccuped. A production build from GitHub that runs out of memory is also retried once a month, automatically, with more build memory.
Where is the full build log on Canner?
On the deployment’s page in the dashboard, streamed live while it builds. An AI agent can read it through the MCP tool canner_get_deployment.
Builds that tell you what went wrong.
Every failed deploy on Canner names the cause and the fix, with the full log one click away.