Troubleshooting
Search this page for the text you saw. Each entry gives the message as Flisk prints it, the cause, the fix, and where in the repository the message is defined. Every entry also says how it was checked:
- Reproduced: the output below was captured by running Flisk 1.3.86 (
origin/mainat the time of writing) in a scratch project on macOS. The scratch project’s directory is shown as<project>.flisk upwas not run for this page, so nothing here was observed while Docker was starting containers. - Simulated: produced by running the real
fliskagainst a stand-in for Docker (a small wrapper that makesdockerfail the way the entry describes). The message and fix are Flisk’s own; the Docker failure itself was not real. - Read from source, not reproduced: copied from the code. It is the intended text; whether your situation produces it was not checked.
Where the cause is not known, the entry says so. Messages change between releases: if yours differs slightly, search for the first few words.
Fixes that change files or Docker state, such as flisk down --prune-networks or docker network prune, affect every project on that Docker daemon, not only the one you are in.
flisk fails before anything starts
Could not find project root
$ flisk status # also: flisk up
Error: Could not find project root (no .flisk/project.json found). Run `flisk project --yes` first.
- Cause: you ran the command outside a Flisk project. Flisk looks upward from the current directory for
.flisk/project.json. - Fix:
cdinto the project, or runflisk project --yesto create one. - Defined in:
errors.ts(requireProjectRoot,errorFactories.notInProject). Some commands print the second wording fromerrorFactories,❌ Could not find project root (no .flisk/project.json found), followed by suggestions. - Checked: reproduced (
flisk statusandflisk up, exit code 1).
unknown option and unknown command
$ flisk resource x --bogus
error: unknown option '--bogus'
$ flisk upp
error: unknown command 'upp'
(Did you mean up?)
- Cause: a typo, or a flag the command does not have. The exit code is 1.
- Fix:
flisk <command> --helplists the flags. - Checked: reproduced.
- If an older Flisk reports
unknown flag: --force, upgrade it. Current Flisk accepts the option for script compatibility and does not pass it to Tilt. The historical pilot report rantilt down --forcedirectly, notflisk down --force.
Stack "x" not found
$ flisk up nope --dry-run
❌ Stack "nope" not found
💡 Suggestions:
→ Run `flisk stacks` to see available stacks
→ Run `flisk stack` to assign resources to a stack
- Cause: no resource is assigned to a stack of that name. Stacks are the
<stack>folder inservices/<stack>/<name>/. - Fix:
flisk stackslists what Flisk found. - Defined in:
errors.ts(stackNotFound).Resource "x" not foundis the same pattern. - Checked: reproduced for the stack message; the resource message was read from source, not reproduced.
Required secrets: secret X has no value
$ flisk up --dry-run
❌ 1 required secret without a value:
services/main/api/service.json: secret SECRET_KEY has no value
Fix: Add NAME=value to .env (it is gitignored), or export it in the environment, or move it to "optional"
- Cause: the service lists
SECRET_KEYinsecrets.required, and neither the env file of the run (the project.env, or the one chosen with--env-file) nor the environment has a non-empty value for it. Compose refuses to interpolate such a name, which used to fail the whole Tiltfile and stop every service. - Fix: put
SECRET_KEY=...in.env, export it, or list it undersecrets.optionalif the service can run without it. WithFLISK_SECRET_PROVIDER=infisicalthe check is skipped and Infisical supplies the names. - Defined in:
service-config-checks.ts(checkRequiredSecrets), run by theflisk upgate, dry run included. - Checked: reproduced by the Docker chaos tier (
secrets=required, no value) and covered byservice-config-checks.test.ts.
flisk X is older than the Y this project requires (minFliskVersion)
$ flisk up shop --dry-run # same text from flisk up and flisk doctor
flisk 1.3.86 is older than the 9.9.9 this project requires (minFliskVersion)
Run: flisk upgrade
With "minFliskVersion": "abc" in .flisk/project.json:
.flisk/project.json minFliskVersion "abc" is not a version like "1.3.80"
Set minFliskVersion to a MAJOR.MINOR.PATCH string, for example "1.3.80".
- Cause: the repository pins a minimum CLI version and yours is older, or the pin is not
MAJOR.MINOR.PATCH. Both stopflisk upwith exit code 1, before Docker or Tilt are touched. - Fix:
flisk upgrade, or install a specific version; see upgrading.flisk up --ignore-versionskips the check, which is only sensible when the pin is stale. - Defined in:
flisk-version.ts. - Checked: reproduced with a scratch
minFliskVersionof9.9.9andabc.
Cold start blocked (Docker or Tilt missing)
flisk up checks the machine before anything else. With a Docker that cannot be reached (simulated with a wrapper that answers like a stopped daemon):
$ flisk up shop
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?
Cold start blocked. Bun/Prisma/NATS are not the first failure.
They are generated after `flisk project`. Fix the machine checks below.
FAIL docker Docker daemon is not running
Start Docker Desktop, OrbStack, or Colima, then retry: flisk doctor
FAIL compose Docker Compose plugin not found
Install Docker Compose: https://docs.docker.com/compose/install/
With tilt removed from PATH (reproduced):
Cold start blocked. Bun/Prisma/NATS are not the first failure.
They are generated after `flisk project`. Fix the machine checks below.
FAIL tilt Tilt CLI not found
curl -fsSL https://raw.githubusercontent.com/tilt-dev/tilt/master/scripts/install.sh | bash
- Cause: no Docker daemon, no Compose plugin, or no Tilt on
PATH. The Compose line appears with the daemon line here because the stand-in made everydockercall fail; with a real stopped daemon, whether it also prints is not checked. - Fix: start Docker Desktop, OrbStack or Colima, or install Tilt, then
flisk doctor. - Defined in:
cold-preflight.tsandDOCTOR_FIXESindoctor.ts. - Checked: Tilt missing reproduced; Docker down simulated. Other texts in the same family, read from source, not reproduced, from
errors.ts:Tilt CLI is not installed,Docker (or a compatible container runtime) is not running,Docker is running but not responding (docker pshung for 10s)(fix: quit and reopen Docker Desktop, orcolima restart), all underFlisk can't start - missing prerequisites:. - Only
flisk upis blocked:flisk projectwrites the project configuration and clones a starter template without a Docker daemon or Tilt, and prints the next step instead.flisk doctorremains the explicit readiness check. - See also: Troubleshoot Docker layers (L1–L4 overview) for identifying which layer broke a Docker build and how to rebuild golden layers.
- See also: Troubleshoot L1 (base image) build failures for failures pulling the upstream base image, Alpine package installation errors, or missing golden layers.
- See also: Troubleshoot L2 (dependency layer) build failures for package installation, lockfile synchronization, and Docker layer caching issues.
Out of sync: ... from flisk config verify
$ flisk config verify
🔍 Verifying configuration...
⚠️ Configuration issues found:
- Out of sync: .flisk/.flisk-out/TILT_TECH_STACK.star (run 'flisk config regenerate')
- Out of sync: .tiltignore (run 'flisk config regenerate')
--- a/.flisk/.flisk-out/TILT_TECH_STACK.star
+++ b/.flisk/.flisk-out/TILT_TECH_STACK.star
...
Run `flisk config regenerate` to fix.
(The diff shows the whole file as changed, with the same text on both sides; only the line you edited differs. This output came from appending one line to each file.)
- Cause: a generated file was edited by hand, or
.flisk/project.jsonchanged since the files were generated. The message appears with the same text for a.tiltignorethat Flisk wrote and someone edited (gradual adoption covers a.tiltignoreFlisk did not write). - Fix:
flisk config regenerate. It restores a root.tiltignorethat still carries Flisk’sSYSTEM-GENERATED BY Flisk CLIheader and printsRestored: .tiltignore → project root (hand edits discarded); your edit is gone, so keep a copy if you want it. A.tiltignorewithout that header is never overwritten (it is the team’s own).flisk project --yesdoes not restore it. Before this was fixed,flisk config regenerateleft the edited file as it was and the only way out was to delete the root.tiltignoreand runflisk config regenerateagain. - Defined in:
template-engine.tsandconfig.ts. - Checked: reproduced, including the failing fix and the workaround.
flisk doctor fails
flisk doctor prints ✗ for a failure, ○ for a skipped check and ℹ Fix: under a failure. It exits 1 when any check fails. The JSON form is described in the doctor contract. The scratch outputs below used flisk doctor --no-ping, which does not call running services.
Docker and Tilt
All read from source, not reproduced except where stated. Defined in doctor.ts unless noted.
| Message | Fix as printed |
|---|---|
Docker is not running / Docker daemon is not running (also reproduced through a stand-in, see above) |
Start Docker Desktop, OrbStack, or Colima, then retry: flisk doctor |
Docker daemon is not responding |
Same fix text |
Colima is installed but not running |
Same fix text |
Docker is using the <os> engine; Flisk requires Linux containers |
Switch Docker Desktop to Linux containers, enable WSL2 integration, then retry flisk doctor |
Docker is too old for generated healthchecks (they use start_interval), followed by the versions found |
Update Docker Desktop, or on Linux update docker-ce and the docker-compose-plugin package. The README states Engine 25+ and Compose 2.20+ |
Tilt CLI not found (reproduced) |
The Tilt install script, as in the entry above |
Tilt <version> is below the required v0.25.0 floor |
Install Tilt v0.25.0 or newer: https://docs.tilt.dev/install.html |
Bun is not available / Bun <version> is below the required 1.2.0 floor |
curl -fsSL https://bun.sh/install \| bash, or install Bun 1.2.0 or newer. Checked only when the project has generated JavaScript services |
Podman: doctor prints Podman is running when it is the runtime it finds, and Docker daemon is not running otherwise. Whether a Podman setup can run a whole stack was not checked.
Docker build cache exceeds 10 GB threshold
⚠ 11.82GB across 780 entries: Docker build cache exceeds 10 GB threshold. Cache is shared across all projects on this machine
ℹ Fix: Prune old build cache: flisk down --prune-cache (or docker builder prune --filter until=24h). Note: this affects other projects on this machine.
- Cause: Starting stacks builds golden base image layers and mounts package caches (
RUN --mount=type=cache,target=/cache/bun) so builds take seconds instead of minutes. Over time, Docker build cache grows by several gigabytes. Because Docker build cache is daemon-global, it is shared across all projects on the machine. - Fix: Run
flisk down --prune-cachewhen stopping your stack. It safely prunes cache older than 24 hours (docker builder prune -f --filter until=24h), preserving warm cache for recent builds while reclaiming gigabytes of disk space. Customize the retention window with--cache-until <age>(e.g.flisk down --prune-cache --cache-until 7d). In interactive terminals, it prompts for confirmation; pass-y/--yesin scripts. Or runflisk doctor --fixwhen host disk space is low (< 10 GB). - Checked: tested with mocked
docker system dfand unit tests pinning the 10 GB threshold and guarded pruning.
Docker cannot create another network: all predefined address pools are in use
✗ Docker cannot create another network: all predefined address pools are in use. Each Flisk project needs several
ℹ Fix: Run flisk doctor --fix --scope=machine: it removes unused networks of every Flisk project and keeps the ones in use. Or run flisk down --prune-networks in each project you are not using
- Cause: Docker’s default address pools are used up. Each Flisk project creates several networks and keeps them after
flisk down. Docker’s own error text isall predefined address pools have been fully subnetted; doctor matchesaddress pools. - Fix: run
flisk doctor --fix --scope=machine. It lists every unused network that belongs to a Flisk project (each with its owner), skips any network with a container attached, and asks before it removes them; add--dry-runto only list them. Alternatives:flisk down --prune-networksin each project you no longer use, ordocker network prune, which removes every unused network on that Docker daemon, whoever created it.--prune-networkswas added in #585. - If you skip doctor: since #589, the
init-networksresource in Tilt fails withFailed to create Docker network <name>: <Docker's message>and exits 1. Before it, the failure was swallowed (the command ended|| true),init-networksreported success, and the later failure wasnetwork ... declared as external, but could not be found, which is what byo.md and the moon recipe describe. TheFailed to create Docker networktext is inutils_docker_networks.star. - Checked: the doctor message is simulated (the stand-in
dockerfailednetwork createwith Docker’s text). Theinit-networksfailure was reproduced on 2026-10-27 (macOS, Colima, 32 networks, 25 of them unused):Failed to create Docker network helpdock_backend: Error response from daemon: all predefined address pools have been fully subnetted. Removing the unused networks of other Flisk projects let the nextnetwork createsucceed.
Note that flisk doctor itself runs docker network create flisk_doctor_probe_<pid> and removes it, to test whether a network can be created.
Environment variables
$ flisk doctor --no-ping # no .env file
✗ Missing required env variables: TILT_ENV, DB_PASSWORD
ℹ Fix: No .env file yet. Run `flisk project` to create one with working defaults.
# .env exists but TILT_ENV was deleted from it
✗ Missing required env variables: TILT_ENV
ℹ Fix: Edit .env and set these values:
TILT_ENV=<value>
# DB_PASSWORD= is present but empty
✗ Invalid env variables: DB_PASSWORD is set but empty
ℹ Fix: Edit .env and provide values for empty variables
- Cause: a required key is absent or empty in the project
.env. See environment. - Fix: as printed.
flisk projectwrites a.envwith working defaults and does not need Docker. - Defined in:
doctor.ts(checkEnvironmentVariables) andenv-validator.ts. - Checked: reproduced, all three. When only a warning applies, doctor passes and appends
(warning: ...); for example aDATABASE_URLpassword that differs fromDB_PASSWORD(read from source, not reproduced).
Public environment secrets (NEXT_PUBLIC_*, VITE_*)
⚠ Potential secret-looking values detected in public environment variables: NEXT_PUBLIC_API_KEY (.env)
ℹ Fix: Move secrets to server-side variables or API routes. Public variables (NEXT_PUBLIC_*, VITE_*) are embedded into client bundles.
- Cause: a client-accessible variable prefixed with
NEXT_PUBLIC_(Next.js) orVITE_(Vite) holds a value that matches high-confidence credential signatures (for example Stripe secret keyssk_live_, AWS credentialsAKIA, GitHub tokensghp_, OpenAI keyssk-proj-, Slack tokensxoxb-, Google API keysAIza, private keys, JWTs, or embedded URL credentials). The bundler inlines these values directly into the browser-facing JavaScript bundle where any visitor can inspect them. - Warning-only: this check is an informational warning (
⚠) by default, so it does not failflisk doctoror block local developer workflows. When run withflisk doctor --strict, it is treated as a blocking failure. - Redaction:
flisk doctoroutputs only the variable name and the relative file path. Secret values are never printed in diagnostic messages, error output, JSON envelopes, or logs. - Publishable keys allowed: known public-by-design identifiers, such as Stripe publishable keys (
pk_live_,pk_test_) and common placeholders (sk_test_x), are recognized and permitted. - Fix: rotate any leaked credential immediately. Move calls that require secrets to server routes, API endpoints, or a backend-for-frontend (BFF) proxy so client code never receives secret tokens.
- Defined in:
public-env-secrets.tsanddoctor.ts(checkPublicEnvSecrets).
TOOLCHAIN_MISMATCH: a service needs another runtime version
✗ api: wants node@24 (service.json), node 20.11.0 is on PATH
Switch to that version with your version manager, or change "toolchain" in the service.json.
- Cause: a local-process service declares
"toolchain": "node@24"(or[email protected], …) in itsservice.json, and the program onPATHis another version, is missing, or did not report a version.flisk upstops before starting anything;flisk doctorfails the Service toolchains check. - Hints: without
toolchain, a.nvmrc,.node-versionor.python-versionin the service folder is compared too, but a mismatch there is only a warning inflisk doctorand never stopsflisk up. - Fix: switch versions with your version manager (nvm, fnm, mise, pyenv, …), or change
toolchain. Container services are not checked: their image decides the runtime. - Defined in:
toolchain.ts.
Env values that point outside the local stack
⚠ 2 values point outside the local stack:
orders-api DATABASE_URL -> db.shared.example.com (services/shop/orders-api/.env.local)
(project) AUTH_ISSUER -> auth.dev.example.com (.env)
ℹ Fix: Point them at a local service (http://<service>:<port>, *.localhost), or list hosts that are meant to be remote in "allowedHosts" in .flisk/project.json
- Cause: a URL, or a
*_HOST/*_HOSTNAME/*_DOMAINvalue, names a host that is not part of the local stack. Flisk reads the project.env, each service’senvandparamsinservice.json, and.env,.env.local,.env.developmentand.env.development.localin each service folder. The service then talks to a shared or production system while you think it runs locally, which shows up as data in shared environments or unexplained 401s. - Local:
localhost,*.localhost,*.local,*.internal, loopback and private IP addresses, one-word names (Compose services and containers on the stack network), and the names of the project’s services and stacks. - Warning-only: a warning (
⚠) by default;flisk doctor --strictfails on it. - Redaction: only the service, the variable name, the host and the file are printed, never the value.
- Fix: point the value at the local service, or add the host to
allowedHostsin.flisk/project.jsonwhen it is meant to be remote ("*.stripe.com"matches every subdomain). - Defined in:
remote-env-hosts.ts(checkRemoteEnvHosts).
Project files that do not match what Flisk expects
✗ 1 resource without a package.json: billing-api. The image build stops at "COPY .../package.json: not found"
ℹ Fix: Add a package.json next to each service.json (copy one from a working resource), or delete the folder's service.json if it is not a service
✗ Services missing required package.json scripts:
orders-api: missing "build"
ℹ Fix: Add the missing scripts to each service's package.json, e.g.:
"dev": "bun run src/index.ts",
"build": "tsc",
"start": "bun run dist/index.js"
✗ 1 resource outside discovery.paths ["services/*/*"]: other/deep/x/billing-api. `flisk up` will not start them
ℹ Fix: Move each under services/<stack>/<name>, or add a matching pattern to discovery.paths in .flisk/project.json and run: flisk config regenerate
✗ Master configs missing: TILT_TECH_STACK.star
ℹ Fix: Run: flisk project
- Cause and fix: as printed. The last one also produces a second failure,
Starlark load() issues will stop Tilt before services start:, listing the missing file; its fix isflisk config regenerate. - Defined in:
doctor-wiring.ts(package.json),doctor.ts(scripts, discovery, master configs, Starlark). - Checked: reproduced, each by changing one thing in a scratch project. A defect was noted in adopt-flisk.md: on the code that page was written against,
N resources without a package.jsonwas also reported for bring-your-own resources. It was not re-run for this page.
Backends without a health route
✗ Backends without a health route (the container never turns healthy, so Traefik returns 404):
orders-api: no "/health" route in src/ (probed by the container and Traefik healthchecks)
ℹ Fix: Add the route, e.g. for Hono: app.get("/health", (c) => c.json({ status: "ok" })). To use a different path, set "healthCheckPath" (container healthcheck) or "traefik.healthCheck" (Traefik) in its service.json.
- Cause: the check searches
src/for the health path fromservice.jsonand found none. The scratch case renamed/healthto/healthzin a scaffolded backend. Per the message, a service with no health route never turns healthy and Traefik answers 404 for it; that part was not observed, becauseflisk upwas not run. - Fix: add the route, or point
healthCheckPathandtraefik.healthCheckat the path you use. - Defined in:
doctor-runtime.ts. - Checked: reproduced (the doctor message only).
Unknown service.json field ...: unknown field is preserved
⚠️ <project>/services/shop/orders-api/service.json.healthCheck: unknown field is preserved
- Cause:
service.jsonhas a key Flisk does not know. Flisk leaves it in place. The scratch case added"healthCheck": "/health"by hand; doctor still exited 0. - Fix: none required. Remove the field, or fix its spelling, if you expected it to do something. Pilot Flisk on a real repository records that on Flisk 1.3.86 a freshly scaffolded service produced this for
healthCheck; a service scaffolded by the version used for this page did not. - Defined in:
service-manifest.ts. The warning’s wording wasUnknown service.json field: ...in the earlier capture and is<path>.<field>: unknown field is preservednow. - Checked: reproduced.
Docker Model Runner: a service declares models
⚠ nosia declares models, but this Docker has no `docker model` plugin; Compose will refuse to start it ("'models' support requires Docker Model plugin")
ℹ Fix: Enable Docker Model Runner in Docker Desktop, or install docker-model-plugin (Docker Engine on Linux), then run: docker model install-runner
- Cause: a bring-your-own
service.jsonhasmodels(Composemodels:, served by Docker Model Runner) anddocker model versionfails. A second wording says the plugin is installed butdocker model statusreports the runner is not running, so no model can be served. Both are warnings:flisk doctorandflisk upprint them and carry on. - Fix: Docker Desktop: Settings > AI > Enable Docker Model Runner. Docker Engine on Linux: install
docker-model-pluginfrom Docker’s apt repository, thendocker model install-runner. The check passes whendocker model statusexits 0; it does not pull or run a model. - Defined in:
service-config-checks.ts,checkModelRunner. - Checked: the message paths by unit tests with the Docker answers faked, and the
docker modelcommands against Docker Desktop (plugin installed, runner not running). Not run against Docker Engine on Linux.
Other doctor failures, read from source
All read from source, not reproduced.
| Message (start of it) | Cause as the message states it | Fix as printed | Defined in |
|---|---|---|---|
N Tilt processes are running for this project (pids ...). They fight over ports and containers |
More than one Tilt for this project | flisk down && kill <pids> && flisk up |
doctor-wiring.ts |
Another project's Tilt is running: ... |
Another project’s Tilt holds a UI port | flisk up uses the next free Tilt UI port (10351, …); if it is a leftover, run flisk down in that project |
doctor-wiring.ts |
N migration command(s) run from a backend or worker's own start-up |
A service migrates on every start | Move the migration into a migrator resource the service depends on; see byo |
doctor-wiring.ts |
N service URL(s) in params that cannot connect |
A URL in params points at the wrong port |
Containers reach each other as http://<resource>:<port>, using the port in that service’s service.json |
doctor-wiring.ts |
N frontend call(s) to a backend port that Flisk does not publish on localhost |
A frontend calls localhost:<backend port> |
Use the Traefik URL http://api.<project>.localhost/api/<name without -api>/... |
doctor-wiring.ts |
... enable the nats feature, but no NATS server will start |
services/platform/messaging/docker-compose.yml is missing and Flisk does not generate it |
Create it with a nats service and a redis service, as the Fix line describes |
doctor-wiring.ts |
Generated Dockerfiles reference missing project runtime assets |
Generated files are older than the CLI | flisk project --yes or flisk config regenerate with an updated Flisk |
doctor.ts |
Starlark load() issues will stop Tilt before services start |
A generated .star file loads something that is missing |
flisk config regenerate |
doctor.ts |
bun run build will fail with TS2688 (Cannot find type definition file) |
A types entry in the Docker tsconfig has no @types package in devDependencies |
Add the packages the Fix line lists | doctor.ts |
Frontend Docker metadata has issues that will make flisk up fail or route 404 |
Generated frontend metadata is stale | flisk config regenerate; make sure the nginx runtime routes to port 80 |
doctor.ts |
N container(s) pinned near its memory limit while burning CPU -- likely stuck in a boot-time retry/fetch loop |
Cause is not known; the message suggests a boot-time retry loop | Read docker logs <container>; the Fix line names AUTO_MIGRATE=false as a temporary unblock when a Prisma auto-migration is the cause |
doctor.ts |
Tilt reports N failed resource(s): |
A Tilt resource failed to update | Read the resource’s log in the Tilt UI or flisk logs |
doctor-runtime.ts |
Private npm registry (Verdaccio) is not reachable at ... |
Verdaccio is expected by the project but not answering | Start it as the Fix line says. Verdaccio needs a Premium licence (features) | doctor-runtime.ts |
Tilt is not running - skipped resource status check (a skip, not a failure) |
You have not run flisk up |
flisk up |
doctor-runtime.ts |
container is running, but its health check is failing, and the probe says curl: not found
❌ flisk up failed:
lychee-facial-recognition: container is running, but its health check is failing
$ docker inspect --format '{{range .State.Health.Log}}[{{.ExitCode}}] {{.Output}}{{end}}' <container>
[127] /bin/sh: 1: curl: not found (exec form: [-1] OCI runtime exec failed: ... executable file not found in $PATH)
- Cause: the image’s health command (often imported from a Compose
healthcheck) does not exist in the image, so the probe never runs while the app itself serves. Docker records that as exit 127 (or 126, not executable) for a shell-form check, and as exit -1 withOCI runtime exec failed ... executable file not foundfor the exec form (test: [CMD, curl, ...]) that Flisk writes. Flisk waits on Docker’s health status, soflisk upused to fail on it. - What Flisk does now: when the container is running and every recorded probe shows its command never ran,
flisk upand the<service>-healthywait proceed with a warning instead of failing. The evidence is in the probe’s own result: exit -1 withOCI runtime exec failed(exec form), exit 127 withnot foundin the output, or exit 126 withpermission deniedand the like (shell form). An exit code alone is not enough, since a script that did run can exit 127. Docker keeps only the last five probes, so for the shell form the whole failing streak must be inside that log; an older real failure that scrolled out leaves the container unhealthy. A probe that runs and fails (any other exit code, a mix with a real failure, or a timeout) still blocks. Unix hosts, the CLI readiness check and the native Windows script follow the same rule. - Fix: the probe still does not work, so fix it when you can: use a command the image has (
python3 -c ...,wget), or sethealthCheckin the service’sservice.json. - Defined in:
apply_compose_resource_registration.star,_HEALTHY_SCRIPT, andup-readiness.ts,healthProbeCannotRun. - Checked: reproduced with
ghcr.io/lycheeorg/lychee-facial-recognition(exit 127,curl: not found) and with live containers intests/tilt-engine/test_dependency_conditions.py. The PowerShell twin is not run off Windows.
Ports
Traefik cannot bind ingress ports because another container already owns them
✗ Traefik cannot bind ingress ports because another container already owns them:
<container name> (host ports <ports>)
ℹ Fix: Stop the foreign container(s), e.g. `docker stop <container name>`, or shut down the other Flisk/Tilt project using that Traefik. Then re-run `flisk up`.
- Cause: a Docker container that is not this project’s already publishes the ingress ports (80 and 443 when they are free, otherwise 8080 and 8443).
- Fix: stop that container only if it is yours to stop, or move Flisk to other ports with
FLISK_HTTP_PORT,FLISK_HTTPS_PORTandFLISK_POSTGRES_PORT. On a shared Docker daemon the container may belong to someone else. - Defined in:
doctor-runtime.ts(checkIngressPorts). - Checked: read from source, not reproduced; it needs a second container on the ingress port.
Ports Flisk needs are taken
✗ Ports Flisk needs are taken:
5432 (<name>) is used by a program on this machine; inspect it with lsof -nP -iTCP:5432
ℹ Fix: Stop local Postgres or change the host port. Then: flisk doctor
The same check prints Stop the process bound to port 80, or stop local nginx/caddy. Then: flisk doctor when the first port found taken is 80, and for 443 Stop the process bound to port 443. Then: flisk doctor. The names in the middle line come from HOST_PORTS in the source; the exact label text was not captured.
- Cause: something other than this project holds 5432, 80 or 443 (a local Postgres is the case the message is written for). With Docker holding 5432, the line says
is published by container <name>. - Fix: stop the program, or choose other host ports with
FLISK_POSTGRES_PORT. The default host ports are 80 and 443 for HTTP and HTTPS, and 15432 for Postgres (Flisk does not try 5432). Flisk picks the next free one when a default is busy; see the FAQ. How the 5432 check relates to the default of 15432 was not investigated. - Colima on macOS: if a port is published in the VM but nothing listens on the Mac (
UP_URL_UNREACHABLE,Nothing listens on the gateway port), Colima’s port forwarder has stalled: runcolima restart. Check withlsof -nP -iTCP:80 -sTCP:LISTEN, which showslimactlwhen it is forwarding. - Defined in:
doctor-runtime.ts(checkHostPorts). - Checked: read from source, not reproduced.
FLISK_HTTP_PORT=... is already in use
$ FLISK_HTTP_PORT=18777 flisk up shop --dry-run # something already listening on 18777
Error: FLISK_HTTP_PORT=18777 is already in use. Choose a free host port and retry.
$ FLISK_HTTP_PORT=18777 flisk doctor --no-ping
✗ FLISK_HTTP_PORT=18777 is already in use. Choose a free host port and retry.
ℹ Fix: Set FLISK_HTTP_PORT, FLISK_HTTPS_PORT, or FLISK_POSTGRES_PORT to available host ports.
✗ Ingress port plan is unavailable
- Cause: you set the variable explicitly and that port is taken. Flisk does not fall back to another port when you chose one, and it does not stop the program using it.
- Fix: pick a free port. Without the variable, Flisk picks the next free one itself.
- Defined in:
host-port-plan.ts. - Checked: reproduced with a stand-in listener.
No available host port in ... for ...
No available host port in 15432-15532 for postgres. Set FLISK_POSTGRES_PORT to a free port and retry.
- Cause: every candidate port for that service is taken, usually because many projects are running. HTTP, HTTPS and Postgres each have a range of 101 ports (8080-8180, 8443-8543 and 15432-15532). Every project takes a Postgres port from its range, so at most 101 projects fit with the defaults, fewer if other programs hold ports in it. HTTP and HTTPS try 80 and 443 first and take a port from their range only when that port is not usable, so the first project does not use up a range port. The message names the first service whose candidates run out. That is
postgreswhen 80 and 443 are both usable,ingressHttpwhen 80 is not (it is taken, or on Linux and WSL2 a non-root user cannot check it), andingressHttpswhen only 443 is not. - Fix: stop projects you no longer need with
flisk down, or set the variable the message names for this project:FLISK_HTTP_PORTforingressHttp,FLISK_HTTPS_PORTforingressHttps,FLISK_POSTGRES_PORTforpostgres. The ranges cannot be changed. An override is used as-is: if that port is taken, Flisk reports it instead of picking another. - Defined in:
host-port-plan.ts. - Checked: read from source, and the planner (not
flisk up) was exercised with a stubbed port probe inhost-port-plan.test.ts; not reproduced with real concurrent projects.
Port 10350 is already in use / Auto-switching to port ...
⚠️ Port 10350 is already in use
🔄 Auto-switching to port <port>
- Cause: another process, usually another project’s Tilt, already uses Tilt’s UI port 10350. Flisk uses the next free port, so the Tilt UI for this project is at that port, not 10350.
- Fix: none needed; open the UI on the port printed. If the other Tilt is a leftover,
flisk downin that project. - Defined in:
up.ts. Withflisk up --only, a Tilt that is already running stops it withA Tilt is already running on port ...: runflisk downfirst, or pass --force to replace it. - Checked: read from source, not reproduced; it is printed after the dry-run exit point, so it needs a real start.
Two services on the same port, no message at all
flisk resource a --port 4000 followed by flisk resource b --port 4000 created both resources, with "port": 4000 in each service.json, and flisk doctor --no-ping passed. There is no warning. Without --port, flisk resource picks the next free port in 4000-5999. Whether two services on one port fail at flisk up was not checked. Use distinct ports.
Services never turn healthy, or are left behind
Advertised Endpoints: N advertised link(s) return 404
⚠ 1 advertised link returns 404 (the service may be healthy, but nothing answers at this exact path):
<name> (404)
<url>
- Defined in:
doctor-runtime.ts,summarizeAdvertisedProbes. Doctor requests the URL each routable service advertises (the oneflisk networksand the Flisk App show) and warns, without failing, when one answers 404. - Cause:
/healthis fine, but nothing handles the exact path of the advertised link, usually an API with no root route. - Fix: leave it, or add a
GETroute for that path. A stopped stack is skipped, not reported: the check only runs once services answer. - Checked: read from source, not reproduced.
HTTP 404: Traefik is answering but has no route for this URL
✗ N service(s) not healthy (M/K healthy):
<name> (HTTP 404: Traefik is answering but has no route for this URL (container not started yet, or not running))
<url>
ℹ Fix: If `flisk up` just started, images may still be building: re-run `flisk doctor` in a minute. Otherwise check `docker ps` and the resource in the Tilt UI, and compare `flisk networks` with the URL above.
A 502, 503 or 504 prints Traefik found the route but the container isn't answering (still starting, or unhealthy) instead.
- Cause: per the message, Traefik is up and no running container is registered for that URL. The reasons the source gives are a service still building or not started. Backends without a health route is one way a container never becomes healthy.
- Fix: wait and re-run
flisk doctor; otherwise check the resource in the Tilt UI andflisk networks. - Seen once with a puzzle: during earlier work on this repository, doctor printed this 404 right after startup for a URL that had already answered 200 when fetched directly. That was not investigated, so a 404 right after startup is not proof the service is broken.
- Defined in:
doctor-runtime.ts(describeProbeFailure,summarizeServiceProbes). - Checked: read from source, not reproduced. A 404 stub on the ingress port could not be tried, because Flisk moved to the next free port while the stub was listening.
flisk down left containers running
Before #585, flisk up shop started Tilt with --focus=shop but flisk down ran tilt down without it, so the stack’s own containers were never removed, and a live tilt up could re-create a container right after it was removed. The PR changed flisk down to pass every discovered stack, to stop this project’s own tilt up first, and added flisk down --prune-networks. Networks created by init-networks are kept after flisk down unless you pass it.
- Fix: use a version that includes #585, then
flisk down. On an older version,docker psshows what is left; stop only containers whose names start with your project’s. - Checked: read from the PR description and merged change, not reproduced.
docker images lists every service twice (:dev and :tilt-<hash>), and old builds fill the disk
<project>_<stack>_<service> dev ddbc536add42
<project>_<stack>_<service> tilt-ddbc536add42 ddbc536add42
- Cause: Tilt builds each image as
<name>:tilt-<hash>, tags it with the:devname the compose service uses, and from then on uses only:dev. Thetilt-*tag stays. Both tags are one image, so the pair costs no space, but after a rebuild the previous build keeps its owntilt-*tag, so a full old image per service stays on disk until Tilt’s own prune. - Fix: the
tilt-image-tagsresource (labelinfra.docker) removes this project’stilt-*tags whenflisk upstarts and each time a build is tagged:dev: the tag on the current image, and old builds. An old build still used by the container compose is replacing goes once that container is removed. A newer build that Tilt has not tagged:devyet is left alone. To keep the tags, runFLISK_KEEP_TILT_TAGS=1 flisk up. On a version without it,docker image rm <name>:tilt-<hash>removes a tag by hand; it never deletes an image another tag still names. - Defined in:
tilt_image_tags.star, registered byload_all_infrastructureininfra-loader.star. - Checked: unit tests with a fake
docker(tilt-image-tags-tilt.test.ts), and the generated script run once in a Colima VM on Docker 29.5.2: six:devservices went from two tags to one with their containers still running, and a:devtag event removed a new alias.
Frontend and backend
The frontend cannot reach the backend URL
Flisk prints no message for this. The page loads, but its calls to the API fail in the browser with a network error, a 404, or a CORS error in the browser console.
How the URL is made: for each frontend, Flisk writes .autogenerated/.env.frontend.autogenerated, and Compose passes it to the container. VITE_API_URL (and NEXT_PUBLIC_API_URL for Next.js) is the backend’s Traefik route, http://api.<project>.localhost/api/<backend name without -api>, or the backend’s apiPath when it sets one. The port is added when Traefik is not on 80. Each backend, mcp or agent resource in the frontend’s dependsOn also gets a VITE_<NAME>_API_URL line. The frontend itself runs on app.<project>.localhost, so every call it makes to the API is cross-origin.
Check these in order:
- The frontend calls
localhost:<backend port>. The Docker stack does not publish backend ports on your machine.flisk doctorwarnsN frontend call(s) to a backend port that Flisk does not publish on localhost. Read the URL fromVITE_API_URL, or importAPI_URLfrom the generated.autogenerated/env.ts, instead of writing it in the code. - The frontend has no backend. Flisk takes the backend from
backendName, otherwise from the first backend,mcporagentresource independsOn. With neither,VITE_API_URLfalls back to/api/<stack>-management, a route that serves Flisk’s own API, not yours. AdependsOnname that is not a backend-side service (a typo, a stack, the shared Postgres, another frontend) gets noVITE_<NAME>_API_URLline, and nothing warns about it. Open.autogenerated/.env.frontend.autogeneratedto see what the frontend got, fixservice.json, and runflisk upto write the file again. - CORS. A backend scaffolded by
flisk resourceallows browser origins on*.localhostsubdomains; the rule and its comment are in the generated source. A backend of your own (bring-your-own, or brought in withflisk import) must allowhttp://app.<project>.localhostitself, or the browser blocks the response. - The backend is not answering. Open the
VITE_API_URLvalue in the browser. A 404, 502, 503 or 504 from Traefik is the Traefik entry above.flisk networkslists the URLs that should answer. - The value is old. The container gets the env file when it starts (a Next.js image copies it to
.envwhen it is built), andVITE_*andNEXT_PUBLIC_*values end up in the browser bundle. After changingdependsOn,backendName,apiPathorFLISK_HTTP_PORT, restart the frontend withflisk restart <frontend>. - Without Docker (services that declare a
command): there is no Traefik and no generated frontend env. Services answer onhttp://localhost:<port>. Pass the API’s URL to the frontend yourself inenv, as in run without Docker, and allow the frontend’shttp://localhost:<port>origin in the API’s CORS.
- Defined in:
env.star(the frontend env file),resolver.star(which backend a frontend gets),generated-cors.ts(the scaffolded CORS rule),doctor-wiring.ts(thelocalhost:<port>warning). - Checked: read from source, not reproduced.
flisk upwas not run for this entry.
Scaffolded code
Frontend bun run build stops with .autogenerated/vite.config... does not exist yet
$ bun run build # in a scaffolded frontend, before any flisk up
.autogenerated/vite.config.build.autogenerated.ts does not exist yet. Flisk engine writes it when flisk up loads this resource (needs Docker); flisk resource and flisk config regenerate do not create it. Run flisk up <stack> once, or point this script at your own Vite config to build on the host.
error: script "prebuild" exited with code 1
- Cause: by design. The Vite config is written by the engine when
flisk uploads the resource, not byflisk resource.devhas the same guard withvite.config.frontend.autogenerated.ts. - Fix: run
flisk up <stack>once, or point the script at your own Vite config. - Defined in:
resource.ts(requireGeneratedViteConfig). - Checked: reproduced (
prebuildonly; the exit code of the script is 1).
TS2591: Cannot find name 'process' in an older scaffold
src/index.ts(33,14): error TS2591: Cannot find name 'process'.
- Cause: older scaffolds had no
typesintsconfig.json, and TypeScript 7 does not include@types/*on its own. The Docker image was not affected, because it uses the engine’s own tsconfig. Fixed for new scaffolds in #586. That PR also recordsCannot find name 'Buffer'for anmcpscaffold. - Fix: in an older service, add
"types": ["node"]undercompilerOptionsintsconfig.jsonby hand. A service scaffolded by the current code already has it. - Checked: the current scaffold was seen to contain
"types": ["node"]; the error itself was read from the PR, not reproduced, because it needs an older scaffold.
Windows and WSL2
Native Windows can run flisk doctor, inspect a project, run flisk demo and start services that each declare a command (without Docker); starting a Docker stack needs WSL2. Setup and the smoke run are in WSL2 setup. All entries here are read from source, not reproduced (no Windows machine was used).
| Message | Fix as printed | Defined in |
|---|---|---|
Native Windows cannot boot a Docker stack; services that declare a command run as local processes. For a Docker stack use WSL2 Ubuntu with Docker Desktop integration. Guide: docs/wsl2.md |
Use WSL2 Ubuntu with Docker Desktop integration | doctor.ts |
Docker Desktop is using Windows containers. Switch to Linux containers. Flisk stacks are Linux images. |
Switch Docker Desktop to Linux containers | windows-doctor.ts |
tilt.exe not found on PATH. Install Tilt from https://docs.tilt.dev/install.html |
Install Tilt | windows-doctor.ts |
Windows reserved port(s) ... for Hyper-V/WSL ... |
The message suggests net stop winnat then net start winnat in an Administrator terminal, or changing Flisk’s ports |
windows-doctor.ts |
Windows did not resolve *.flisk.localhost to 127.0.0.1. Browser URLs with hostnames will fail until you fix hosts or use the 127.0.0.1 URLs printed by flisk networks. |
Fix hosts, or use the 127.0.0.1 URLs from flisk networks |
windows-doctor.ts |
WSL2 detected. Use Docker Desktop WSL integration. Guide: docs/wsl2.md ... Project is under /mnt/c (...); hot reload may be broken. (a warning; a failure with --strict) |
Move the repository under your WSL home directory, for example ~/projects |
doctor.ts |
Docker unreachable from WSL2 (docker version cannot reach the server) |
Enable the distribution under Docker Desktop Resources → WSL Integration and restart Ubuntu (wsl2.md) | wsl2.md |
The same source files hold messages for agent hosts such as Dev Containers and WebContainers (agent-host.ts); they were not collected here.
How to ask for help
If the page does not cover it, or the fix did not work:
- Run
flisk --versionandflisk doctorin the project, and keep the output. Add--no-pingif no stack is running. - Open a bug report. It asks for the
flisk doctoroutput, the Flisk version and your operating system, and for the steps to reproduce. - Include the exact message, not a paraphrase, and say whether
flisk upgot as far as starting Tilt. - For questions that are not bugs, and for what to expect from maintainers, see SUPPORT.md.
Do not paste your .env: it holds a generated database password and JWT secret.