# Docker Compose "variable is not set. Defaulting to a blank string" in CI

> Fix Docker Compose "WARN: The X variable is not set. Defaulting to a blank string" in CI - an unset interpolation variable collapsing an image tag, port, or path to empty.

Source: https://latchkey.dev/learn/docker/docker-compose-variable-not-set-interpolation  
Updated: 2026-06-25

Compose interpolates `${VAR}` from the environment and `.env`. When a referenced variable is unset it warns and substitutes an empty string - which can silently produce a bad image tag, a `:latest` fallback, or an invalid value that breaks `up`.

## Diagnose it: read the resolved config, not the file you wrote

Compose merges override files, interpolates variables, and applies defaults before it does anything. Most Compose failures in CI are visible in the resolved configuration and invisible in the source file, because the value you are debugging came from an unset variable that quietly became an empty string.

```Terminal
# the fully merged, interpolated configuration Compose will actually run
docker compose config

# fail loudly on unset variables instead of silently interpolating empty
docker compose --env-file .env config --quiet || echo "invalid"

# which override files were picked up
docker compose config --services
```

> An unset variable interpolates to an empty string rather than erroring, so `image: myapp:${TAG}` becomes `myapp:` and fails later with a confusing reference error. `docker compose config` shows you the empty value directly.

## Bind mounts behave differently on a runner

- A relative bind source is resolved against the compose file location, not the working directory of the shell that invoked it.
- The host path must exist before `up`. Compose creates missing directories for named volumes but not for bind mounts, and the failure surfaces as a mount error rather than a missing-path error.
- On a CI runner the workspace path differs from your machine, so any absolute host path in a compose file is a portability bug waiting for its first CI run.
- Prefer named volumes for anything that does not genuinely need to be read from the host. They remove the whole class of problem.

## FAQ

### What causes Docker Compose "variable is not set. defaulting to a blank string" in CI?

There are 3 common causes: the variable is unset in the ci environment, no .env file present on the runner, and no default in the interpolation. Compose reads ${VAR} from the process environment and an .env file in the project dir.

### How do I fix Docker Compose "variable is not set. defaulting to a blank string" in CI?

There are 2 fixes depending on which cause you have: provide the variable or a default and pass an explicit env file and require the value. Work through them in order, since the first is the most common.

### What does Docker Compose "variable is not set. defaulting to a blank string" in CI actually mean?

A docker compose up prints WARN[...] The "TAG" variable is not set.

### How do I stop Docker Compose "variable is not set. defaulting to a blank string" in CI happening again?

Use ${VAR:-default} or ${VAR:?required} instead of bare ${VAR}. The prevention section lists 3 changes that keep it from recurring.

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
