## TL;DR

Wrangler needs to know which Cloudflare account owns the worker, and it could not find one. Either no account ID is configured or the token belongs to a different account than the config names. Find your account ID in the Cloudflare dashboard URL or via `wrangler whoami`, set it as `account_id` in `wrangler.toml`, and redeploy. Never copy a teammate's account ID from a shared config.

## The query

```text
"wrangler deploy" failed with "You need to provide a valid account id"
```

## Use this when

- `wrangler deploy` fails with exactly "You need to provide a valid account id".
- The deploy worked for someone else but fails on a fresh checkout or CI runner.
- Multiple Cloudflare accounts exist and the wrong one (or none) is configured.

## Not for

- "authentication error, check your API token" (that is a token problem, separate skill).
- "Error: invalid wrangler.toml" (that is a config syntax problem).
- Deploys that fail after the account ID is accepted (that is a later-stage problem).

## Steps

### Step 1: Check what identity wrangler is using

```bash
npx wrangler whoami
```

Expected output: the logged-in account email and account ID. If this fails, fix auth first. If it shows an account, compare its ID against what the project expects.

### Step 2: Find the correct account ID

```bash
npx wrangler whoami | grep -i "account id"
```

Expected output: the account ID tied to your token. Alternatively, open the Cloudflare dashboard and read the account ID from the URL or the workers overview page. For CI, this value belongs in the project's documented setup, not in a teammate's memory.

### Step 3: Set the account ID in wrangler.toml

```toml
name = "[worker name]"
main = "src/index.ts"
account_id = "[account id]"
```

Expected output: the config now names the account explicitly. Wrangler reads `account_id` from the config file first, so this fixes the "no account id" case and pins the right account in the multi-account case.

### Step 4: Verify the token can access that account

```bash
npx wrangler whoami
```

Expected output: the account listed matches the `account_id` in the config. A token scoped to account A with a config naming account B produces confusing errors downstream. Align them now.

### Step 5: Redeploy

```bash
npx wrangler deploy
```

Expected output: the deploy proceeds past account resolution and either succeeds or fails on a real deployment issue (script size, bindings, routes), which is progress.

### Step 6: Make CI self-sufficient

Record in the deploy runbook: wrangler.toml carries account_id, and CI needs only the API token.

Expected output: the runbook records that the account ID lives in version control (it is not a secret) while the token comes from CI secrets. The next fresh runner deploys without this error.

## Variant phrasings

### wrangler deploy error: authentication error, check your API token
Adjacent auth failure: the token is missing or invalid rather than the account ID. Check `CLOUDFLARE_API_TOKEN` and token permissions.

### wrangler whoami not authenticated after token rotation
The cached session died with the old token. Re-authenticate and confirm the account ID again, since rotation sometimes changes which account the token can see.

### browser automation failed on cloudflare dashboard when agent tried to copy the account id
Do not scrape the dashboard for this. `wrangler whoami` returns the account ID with no browser involved.

## Why it happens

Wrangler resolves the target account from the config file, falling back to the token's account. Fresh checkouts often lack `wrangler.toml` account settings (gitignored or never committed), and CI runners have the token but no config context. Multi-account tokens add the second failure mode: the token sees several accounts and wrangler cannot pick. Explicit `account_id` in the committed config removes both ambiguities at once.

## Edge cases

- The account ID is not a secret. Committing it to the repo is correct and expected. The API token is the secret and must never be committed.
- In a monorepo with several workers, each worker's config needs its own `account_id` if they deploy to different accounts. A root-level config does not propagate.
- `wrangler.jsonc` is the newer config format. The same `account_id` key applies there.
- If the dashboard shows the account but `whoami` shows a different one, the token belongs to a different user or org. Create a token under the right account.
- Deploys to the wrong account (when the ID was valid but wrong) create a worker in someone else's account. Delete it there after redeploying to the right one, or it keeps serving stale code.

## Provenance

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