Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/fix-auth-error-hint-env-var.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"wrangler": patch
---

fix: show actionable hint when `/memberships` returns a bad-credentials error (code 9106)

Previously, `wrangler` threw a raw Cloudflare API error ("Missing X-Auth-Key, X-Auth-Email or Authorization headers") with no guidance. Now it emits a `UserError` explaining that an environment variable such as `CLOUDFLARE_API_TOKEN`, `CLOUDFLARE_API_KEY`, or `CLOUDFLARE_EMAIL` may be set to an invalid value, and suggests running `wrangler logout` / `wrangler login` to re-authenticate.
4 changes: 3 additions & 1 deletion packages/wrangler/src/__tests__/kv/key.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1246,7 +1246,9 @@ describe("kv", () => {
runWrangler("kv key get --remote key --namespace-id=xxxx")
).rejects.toThrowErrorMatchingInlineSnapshot(`
[Error: Failed to automatically retrieve account IDs for the logged in user.
You may have incorrect permissions on your API token. You can skip this account check by adding an \`account_id\` in your Wrangler configuration file, or by setting the value of CLOUDFLARE_ACCOUNT_ID]
You may have incorrect permissions on your API token, or an environment variable such as CLOUDFLARE_API_TOKEN, CLOUDFLARE_API_KEY, or CLOUDFLARE_EMAIL may be set to an invalid value.
Check your environment and unset or correct any Cloudflare credential variables, or run \`wrangler logout\` followed by \`wrangler login\` to re-authenticate.
You can also skip this account check by adding an \`account_id\` in your Wrangler configuration file, or by setting the value of CLOUDFLARE_ACCOUNT_ID]
`);
});

Expand Down
30 changes: 30 additions & 0 deletions packages/wrangler/src/__tests__/user.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,36 @@ describe("User", () => {
);
});

it("should include env-var hint when /memberships returns 9106 and /accounts is empty", async ({
expect,
}) => {
msw.use(
http.get("*/accounts", () => HttpResponse.json(createFetchResult([])), {
once: true,
}),
http.get(
"*/memberships",
() => {
return HttpResponse.json({
success: false,
errors: [
{
code: 9106,
message: "Authentication failed",
},
],
result: null,
});
},
{ once: true }
)
);

await expect(fetchAllAccounts({})).rejects.toThrowError(
/CLOUDFLARE_API_TOKEN/
);
});

it("should propagate /memberships errors that are not 9106 or 10000", async ({
expect,
}) => {
Expand Down
18 changes: 17 additions & 1 deletion packages/wrangler/src/user/fetch-accounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@ import type { ComplianceConfig } from "@cloudflare/workers-utils";
// auth (e.g. tokens missing the membership read scope).
const MEMBERSHIPS_INACCESSIBLE_CODES = [9106, 10000];

function getErrorCode(err: unknown): number | undefined {
return (err as { code?: number } | undefined)?.code;
}

function isMembershipsInaccessible(err: unknown): boolean {
const code = (err as { code?: number } | undefined)?.code;
const code = getErrorCode(err);
return code !== undefined && MEMBERSHIPS_INACCESSIBLE_CODES.includes(code);
}

Expand Down Expand Up @@ -74,6 +78,18 @@ export async function fetchAllAccounts(
// Fall back to `/accounts`, which is already scoped to what the auth can use.
return accountsRes.value;
}
// 9106 specifically can be returned when an environment variable like
// CLOUDFLARE_API_TOKEN is set to an invalid value — surface that hint.
const errCode = getErrorCode(membershipsRes.reason);
if (errCode === 9106) {
throw new UserError(
`Failed to automatically retrieve account IDs for the logged in user.
You may have incorrect permissions on your API token, or an environment variable such as CLOUDFLARE_API_TOKEN, CLOUDFLARE_API_KEY, or CLOUDFLARE_EMAIL may be set to an invalid value.
Check your environment and unset or correct any Cloudflare credential variables, or run \`wrangler logout\` followed by \`wrangler login\` to re-authenticate.
You can also skip this account check by adding an \`account_id\` in your ${configFileName(undefined)} file, or by setting the value of CLOUDFLARE_ACCOUNT_ID`,
{ telemetryMessage: "user account fetch permission denied" }
);
}
throw new UserError(
`Failed to automatically retrieve account IDs for the logged in user.
You may have incorrect permissions on your API token. You can skip this account check by adding an \`account_id\` in your ${configFileName(undefined)} file, or by setting the value of CLOUDFLARE_ACCOUNT_ID`,
Expand Down
Loading