## TL;DR

Cloudflare validates that the custom domain's DNS actually resolves before it lets a worker claim the route. If the domain has no DNS record, points nowhere, or the zone is not active on Cloudflare, the deploy is rejected with origin_dns_error. Create the DNS record (or activate the zone), wait for propagation, and redeploy.

## The query

```text
wrangler deploy failed: workers.api.error.origin_dns_error on custom domain route
```

## Use this when

- `wrangler deploy` fails naming origin_dns_error.
- The route uses a custom domain rather than workers.dev.
- The domain was just registered or just transferred.

## Not for

- 'Worker route already exists' (route conflict, separate fix).
- Zone permission errors (token scope problem).
- Runtime 5xx from the origin after a successful deploy (origin health problem).

## Steps

### Step 1: Check the domain resolves at all

```bash
dig +short [domain] A
dig +short [domain] AAAA
```

Expected result: at least one answer. No answers means there is no DNS record, and no record means the route cannot validate. Create an A, AAAA, or CNAME record for the domain.

### Step 2: Confirm the zone is active on Cloudflare

In the dashboard, check the domain's zone status. A zone stuck in 'pending' (nameservers not yet pointed at Cloudflare) fails route validation even with correct records.

Expected result: zone status 'active'. If pending, finish the nameserver change at the registrar first.

### Step 3: Check the route pattern matches the record

```toml
routes = [
  { pattern = "[domain]/*", zone_name = "[domain]" },
]
```

Expected result: the pattern's hostname matches the DNS record's hostname. A route for `www.[domain]` with only an apex record fails validation.

### Step 4: Wait for DNS propagation, then redeploy

DNS changes can take minutes to hours to be visible to Cloudflare's validators. Verify with an external resolver before redeploying.

Expected result: the record is visible globally, and the redeploy passes validation.

### Step 5: Redeploy

```bash
npx wrangler deploy
```

Expected result: the deploy attaches the route without the DNS error.

## Why it happens

Route attachment is a claim on traffic. Cloudflare refuses to route a domain to a worker when the domain does not resolve, because the route would be dead on arrival and the failure would look like a worker outage. The check runs at deploy time, so DNS problems surface as deploy errors rather than runtime errors.

## Edge cases

- Proxied (orange-cloud) records validate differently from DNS-only records. For worker routes, the record usually needs to exist; the proxy setting matters for traffic flow after validation.
- Subdomain routes need their own records. An apex record does not cover `api.[domain]`.
- Recently transferred domains can have stale glue at the registry. The zone looks right in the dashboard but resolvers disagree; check with multiple public resolvers.
- Removing the DNS record after a successful deploy does not detach the route, but the next deploy re-validates and fails. Keep the record for the life of the route.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_hZaf6HdhU_UT_9zym6EVuA
