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/main at the time of writing) in a scratch project on macOS. The scratch project’s directory is shown as <project>. flisk up was not run for this page, so nothing here was observed while Docker was starting containers.
  • Simulated: produced by running the real flisk against a stand-in for Docker (a small wrapper that makes docker fail 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: cd into the project, or run flisk project --yes to create one.
  • Defined in: errors.ts (requireProjectRoot, errorFactories.notInProject). Some commands print the second wording from errorFactories, ❌ Could not find project root (no .flisk/project.json found), followed by suggestions.
  • Checked: reproduced (flisk status and flisk 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> --help lists 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 ran tilt down --force directly, not flisk 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 in services/<stack>/<name>/.
  • Fix: flisk stacks lists what Flisk found.
  • Defined in: errors.ts (stackNotFound). Resource "x" not found is 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_KEY in secrets.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 under secrets.optional if the service can run without it. With FLISK_SECRET_PROVIDER=infisical the check is skipped and Infisical supplies the names.
  • Defined in: service-config-checks.ts (checkRequiredSecrets), run by the flisk up gate, dry run included.
  • Checked: reproduced by the Docker chaos tier (secrets=required, no value) and covered by service-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 stop flisk up with exit code 1, before Docker or Tilt are touched.
  • Fix: flisk upgrade, or install a specific version; see upgrading. flisk up --ignore-version skips the check, which is only sensible when the pin is stale.
  • Defined in: flisk-version.ts.
  • Checked: reproduced with a scratch minFliskVersion of 9.9.9 and abc.

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 every docker call 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.ts and DOCTOR_FIXES in doctor.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 ps hung for 10s) (fix: quit and reopen Docker Desktop, or colima restart), all under Flisk can't start - missing prerequisites:.
  • Only flisk up is blocked: flisk project writes the project configuration and clones a starter template without a Docker daemon or Tilt, and prints the next step instead. flisk doctor remains 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.json changed since the files were generated. The message appears with the same text for a .tiltignore that Flisk wrote and someone edited (gradual adoption covers a .tiltignore Flisk did not write).
  • Fix: flisk config regenerate. It restores a root .tiltignore that still carries Flisk’s SYSTEM-GENERATED BY Flisk CLI header and prints Restored: .tiltignore → project root (hand edits discarded); your edit is gone, so keep a copy if you want it. A .tiltignore without that header is never overwritten (it is the team’s own). flisk project --yes does not restore it. Before this was fixed, flisk config regenerate left the edited file as it was and the only way out was to delete the root .tiltignore and run flisk config regenerate again.
  • Defined in: template-engine.ts and config.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-cache when 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 / --yes in scripts. Or run flisk doctor --fix when host disk space is low (< 10 GB).
  • Checked: tested with mocked docker system df and 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 is all predefined address pools have been fully subnetted; doctor matches address 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-run to only list them. Alternatives: flisk down --prune-networks in each project you no longer use, or docker network prune, which removes every unused network on that Docker daemon, whoever created it. --prune-networks was added in #585.
  • If you skip doctor: since #589, the init-networks resource in Tilt fails with Failed to create Docker network <name>: <Docker's message> and exits 1. Before it, the failure was swallowed (the command ended || true), init-networks reported success, and the later failure was network ... declared as external, but could not be found, which is what byo.md and the moon recipe describe. The Failed to create Docker network text is in utils_docker_networks.star.
  • Checked: the doctor message is simulated (the stand-in docker failed network create with Docker’s text). The init-networks failure 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 next network create succeed.

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 project writes a .env with working defaults and does not need Docker.
  • Defined in: doctor.ts (checkEnvironmentVariables) and env-validator.ts.
  • Checked: reproduced, all three. When only a warning applies, doctor passes and appends (warning: ...); for example a DATABASE_URL password that differs from DB_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) or VITE_ (Vite) holds a value that matches high-confidence credential signatures (for example Stripe secret keys sk_live_, AWS credentials AKIA, GitHub tokens ghp_, OpenAI keys sk-proj-, Slack tokens xoxb-, Google API keys AIza, 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 fail flisk doctor or block local developer workflows. When run with flisk doctor --strict, it is treated as a blocking failure.
  • Redaction: flisk doctor outputs 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.ts and doctor.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 its service.json, and the program on PATH is another version, is missing, or did not report a version. flisk up stops before starting anything; flisk doctor fails the Service toolchains check.
  • Hints: without toolchain, a .nvmrc, .node-version or .python-version in the service folder is compared too, but a mismatch there is only a warning in flisk doctor and never stops flisk 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 / *_DOMAIN value, names a host that is not part of the local stack. Flisk reads the project .env, each service’s env and params in service.json, and .env, .env.local, .env.development and .env.development.local in 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 --strict fails 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 allowedHosts in .flisk/project.json when 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 is flisk 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.json was 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 from service.json and found none. The scratch case renamed /health to /healthz in 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, because flisk up was not run.
  • Fix: add the route, or point healthCheckPath and traefik.healthCheck at 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.json has 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 was Unknown service.json field: ... in the earlier capture and is <path>.<field>: unknown field is preserved now.
  • 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.json has models (Compose models:, served by Docker Model Runner) and docker model version fails. A second wording says the plugin is installed but docker model status reports the runner is not running, so no model can be served. Both are warnings: flisk doctor and flisk up print them and carry on.
  • Fix: Docker Desktop: Settings > AI > Enable Docker Model Runner. Docker Engine on Linux: install docker-model-plugin from Docker’s apt repository, then docker model install-runner. The check passes when docker model status exits 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 model commands 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 with OCI runtime exec failed ... executable file not found for the exec form (test: [CMD, curl, ...]) that Flisk writes. Flisk waits on Docker’s health status, so flisk up used to fail on it.
  • What Flisk does now: when the container is running and every recorded probe shows its command never ran, flisk up and the <service>-healthy wait proceed with a warning instead of failing. The evidence is in the probe’s own result: exit -1 with OCI runtime exec failed (exec form), exit 127 with not found in the output, or exit 126 with permission denied and 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 set healthCheck in the service’s service.json.
  • Defined in: apply_compose_resource_registration.star, _HEALTHY_SCRIPT, and up-readiness.ts, healthProbeCannotRun.
  • Checked: reproduced with ghcr.io/lycheeorg/lychee-facial-recognition (exit 127, curl: not found) and with live containers in tests/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_PORT and FLISK_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: run colima restart. Check with lsof -nP -iTCP:80 -sTCP:LISTEN, which shows limactl when 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 postgres when 80 and 443 are both usable, ingressHttp when 80 is not (it is taken, or on Linux and WSL2 a non-root user cannot check it), and ingressHttps when 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_PORT for ingressHttp, FLISK_HTTPS_PORT for ingressHttps, FLISK_POSTGRES_PORT for postgres. 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 in host-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 down in that project.
  • Defined in: up.ts. With flisk up --only, a Tilt that is already running stops it with A Tilt is already running on port ...: run flisk down first, 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

⚠ 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 one flisk networks and the Flisk App show) and warns, without failing, when one answers 404.
  • Cause: /health is fine, but nothing handles the exact path of the advertised link, usually an API with no root route.
  • Fix: leave it, or add a GET route 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 and flisk 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 ps shows 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 :dev name the compose service uses, and from then on uses only :dev. The tilt-* tag stays. Both tags are one image, so the pair costs no space, but after a rebuild the previous build keeps its own tilt-* tag, so a full old image per service stays on disk until Tilt’s own prune.
  • Fix: the tilt-image-tags resource (label infra.docker) removes this project’s tilt-* tags when flisk up starts 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 :dev yet is left alone. To keep the tags, run FLISK_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 by load_all_infrastructure in infra-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 :dev services went from two tags to one with their containers still running, and a :dev tag 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:

  1. The frontend calls localhost:<backend port>. The Docker stack does not publish backend ports on your machine. flisk doctor warns N frontend call(s) to a backend port that Flisk does not publish on localhost. Read the URL from VITE_API_URL, or import API_URL from the generated .autogenerated/env.ts, instead of writing it in the code.
  2. The frontend has no backend. Flisk takes the backend from backendName, otherwise from the first backend, mcp or agent resource in dependsOn. With neither, VITE_API_URL falls back to /api/<stack>-management, a route that serves Flisk’s own API, not yours. A dependsOn name that is not a backend-side service (a typo, a stack, the shared Postgres, another frontend) gets no VITE_<NAME>_API_URL line, and nothing warns about it. Open .autogenerated/.env.frontend.autogenerated to see what the frontend got, fix service.json, and run flisk up to write the file again.
  3. CORS. A backend scaffolded by flisk resource allows browser origins on *.localhost subdomains; the rule and its comment are in the generated source. A backend of your own (bring-your-own, or brought in with flisk import) must allow http://app.<project>.localhost itself, or the browser blocks the response.
  4. The backend is not answering. Open the VITE_API_URL value in the browser. A 404, 502, 503 or 504 from Traefik is the Traefik entry above. flisk networks lists the URLs that should answer.
  5. The value is old. The container gets the env file when it starts (a Next.js image copies it to .env when it is built), and VITE_* and NEXT_PUBLIC_* values end up in the browser bundle. After changing dependsOn, backendName, apiPath or FLISK_HTTP_PORT, restart the frontend with flisk restart <frontend>.
  6. Without Docker (services that declare a command): there is no Traefik and no generated frontend env. Services answer on http://localhost:<port>. Pass the API’s URL to the frontend yourself in env, as in run without Docker, and allow the frontend’s http://localhost:<port> origin in the API’s CORS.

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 up loads the resource, not by flisk resource. dev has the same guard with vite.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 (prebuild only; 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 types in tsconfig.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 records Cannot find name 'Buffer' for an mcp scaffold.
  • Fix: in an older service, add "types": ["node"] under compilerOptions in tsconfig.json by 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:

  1. Run flisk --version and flisk doctor in the project, and keep the output. Add --no-ping if no stack is running.
  2. Open a bug report. It asks for the flisk doctor output, the Flisk version and your operating system, and for the steps to reproduce.
  3. Include the exact message, not a paraphrase, and say whether flisk up got as far as starting Tilt.
  4. 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.