TL;DR: The named file is not in the build context, usually because .dockerignore excludes it. Open .dockerignore and add a `!` exception for the file (e.g. `!config/prod.json`), or move the file into the context. The error tells you the two possible causes right in the message; check .dockerignore first.

## The error

```text
ADD failed: config/prod.json: file not found in build context or excluded by .dockerignore: stat config/prod.json: file does not exist
```

## Fix it

1. Verify the file exists in the context root:
   `ls config/prod.json` (from the context dir)
   Expected: either missing (wrong path) or present (ignore rule).
2. Check .dockerignore:
   `grep -n "prod.json|config" .dockerignore`
   Expected: a matching exclude rule, often something broad like `config/` or `*.json`.
3. Add an exception (exceptions must come AFTER the excluding rule):
   `!config/prod.json`
4. Rebuild and confirm the ADD step passes.

## When this applies
- A specific file is named and the error mentions .dockerignore
- Secrets or env files that a broad ignore rule swallowed

## When this does NOT apply
- "COPY failed: no source files were found" (glob matched nothing at all)
- The file genuinely does not exist anywhere (create it or fix the path)

## Versions
All Docker versions, both builders.

## Why it happens
.dockerignore is applied when the client assembles the context, before any instruction runs. ADD then stats the file inside the context and fails. Broad rules like `*` followed by selective `!` re-includes are the usual culprit, and rule order matters: later lines override earlier ones.

## Edge cases
- `!` exceptions do not re-include files inside an excluded DIRECTORY unless you also re-include the directory path components.
- Whitespace and comments in .dockerignore follow gitignore-like rules; a trailing space in a pattern silently changes the match.
- COPY behaves identically here; the error text says ADD but the fix is the same.
