FAQ & Troubleshooting
Common questions and the gotchas behind them.
Where did my dist go? My container task ran but the files aren't in my project.
By default a container task's generates stay inside the container volume —
fast, and reused on the next run, but not copied back to your working directory.
Mark a generate with export: true to copy it back out:
tasks:
build:
image: node:24-alpine
generates:
- path: dist
export: true
cmds:
- npm run buildSee exporting generated files.
Why does my task run every time, even when nothing changed?
A task can only be skipped if it declares src of its own and all of its
dependencies can also be skipped. A task with no src (or whose src matches no
file — check the warnings), or one that depends on such a task, runs every time —
hammerkit can't prove it's up to date. Give each task accurate src/generates.
See caching.
Why did my task rebuild? / Why was it skipped?
Run hammerkit explain <task>: it names the input that caused a
miss — a changed src file, a changed dependency, or a changed task definition
(cmds, image, envs, mounts, …). Editing a command or bumping an image
invalidates the cache just like a source change. To force a run regardless, use
--cache none or hammerkit clean. See
what invalidates a key.
No cache hits in CI, even though the code didn't change.
Almost always the modify-date method on a fresh checkout: git clone resets file
modification times on every run, so a modify-date task always looks changed. Use
the default checksum method in CI (it compares content, which is stable across
checkouts). See checksum vs. modify-date
and the CI caching guide.
Cannot connect to the Docker daemon / docker: command not found.
A task with an image needs a running container engine. Verify with docker info.
If you don't want Docker for a step, remove its image so it runs on the host. See
installation.
A task fails with missing environment variable NAME.
A $NAME reference in envs couldn't be resolved from the shell or a .env file.
Either export the variable, add it to .env, or give the env a literal value.
Hammerkit fails fast here on purpose so a build never runs with a silently-empty
variable. See environment variables.
My task hangs "waiting" for a service that's running.
The service's healthcheck never exits
0, so hammerkit never considers it ready. There's no readiness deadline, so it
waits indefinitely. Make the cmd a real readiness probe (like pg_isready) and
confirm it succeeds inside the container.
My container task can't reach the service.
A container task reaches a service by its name as the hostname on the service's
container port (e.g. postgres:5432) — not via a published ports entry, and
not via the HAMMERKIT_* variables (those are injected only for local tasks).
See services & networking.
Generated files are owned by root (Linux).
On Linux a container task runs as your uid:gid and hammerkit chowns the working
directory and mounts to you, so new files come back owned by you. The chown is
not recursive, so root-owned files baked into the image are left as-is. On
macOS/Windows the Docker Desktop VM handles this. See
file permission.
No tasks found (exit code 127).
The task name you asked for doesn't exist in the resolved build file. Run
hammerkit ls to see the available task names (including
prefix:name ones from references/includes). For the full exit-code contract see
the CLI reference.
Which file does hammerkit use as the build file?
It looks for .hammerkit.yaml, then .hammerkit.yml, then build.yaml, and uses
the first it finds (warning if several exist). Override with --file <path>. See
the build file.