service "web" refers to undefined secret db_password: invalid compose project — the service lists db_password under secrets:, and the file has no top-level secrets: section that says where that secret comes from. Declare it, here as a file, and the project starts.

Add a top-level secrets: block with db_password: and a file: line pointing at a file that holds the value. The service then reads it at /run/secrets/db_password.

The error

PS> docker compose -p fix10-cs-p3 config
service "web" refers to undefined secret db_password: invalid compose project

docker compose -p fix10-cs-p3 up printed the same line and exited with code 1 before creating a network or a container. The file:

services:
  web:
    image: alpine
    command: ["cat", "/run/secrets/db_password"]
    secrets:
      - db_password

Why it happens

A secret in Compose has two halves. The service's secrets: list only says which secrets the container gets; the top-level secrets: section says where each one's value comes from. The service names db_password, and with no top-level entry for it Compose has no value to mount, so it rejects the whole project.

Configs work the same way and give the same kind of message. A second file that listed both an undefined secret and an undefined config under one service stopped on the config:

PS> docker compose -p fix10-cs-pa config
service "web" refers to undefined config app_config: invalid compose project

For that one, add a top-level configs: entry named app_config. With app_config defined and the secret still missing, the same file stopped on the secret line shown above, so fix one and expect the next.

The fix

services:
  web:
    image: alpine
    command: ["cat", "/run/secrets/db_password"]
    secrets:
      - db_password

secrets:
  db_password:
    file: ./db_password.txt
PS> docker compose -p fix10-cs-p3 up
...
Attaching to web-1
 Container fix10-cs-p3-web-1 Starting
web-1  | not-a-real-password-123
 Container fix10-cs-p3-web-1 Started
...

db_password.txt sits next to compose.yaml and holds the value; the container printed it from /run/secrets/db_password, so the secret was mounted. The value here is a test string. For a real one, keep the file out of Git.

How it was reproduced

One alpine service that runs cat /run/secrets/db_password and lists db_password under its secrets:, with no top-level secrets: section, checked with docker compose config and started with docker compose up from Windows PowerShell 5.1; a second file added an undefined config, and a third defined that config but not the secret. Docker Compose v5.7.0, Docker Engine 29.9.3, Docker Desktop 4.99.0 on Windows (version 10.0.26300). The project names fix10-cs-p3, fix10-cs-pa and fix10-cs-pb are this test's own; the started project was removed with docker compose down -v.

Frequently asked

What does 'refers to undefined secret' mean in Docker Compose?
A service lists a secret under its secrets: key, and the file has no top-level secrets: section that defines that name. Compose rejects the project before it creates anything.
How do I define a secret in docker-compose.yml?
Add a top-level secrets: section with the secret's name and a file: line, for example db_password: with file: ./db_password.txt. The container then reads it at /run/secrets/db_password.
Does an undefined config give the same error?
It gives the same kind of message with the word config: service "web" refers to undefined config app_config: invalid compose project. Define it under a top-level configs: section.

More decoded errors in the Fixes category. The same mistake with a named volume is Docker Compose: refers to undefined volume.