Skip to content

Commit 4546050

Browse files
thebenternclaude
andcommitted
feat(v2): report candidate shapes when no token authenticates
"No candidate authenticated" is not actionable. The failure path now describes what was actually on the clipboard, by shape only, never by value: candidate 1: length=50 <- token-shaped, but Cloudflare does not recognise it candidate 2: length=64 <- 64 hex: this is an R2 SECRET ACCESS KEY, not an API token A 64-hex string means the R2 token page was copied instead of the Workers one -- easily done, since both pages present "a long secret value to copy now" and both are reached through the Cloudflare dashboard. Recognising that from the output saves re-minting a token that was never the problem. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent a2bfc1c commit 4546050

1 file changed

Lines changed: 29 additions & 6 deletions

File tree

tools/cf-token.sh

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,35 @@ while IFS= read -r c; do
8484
done <<< "$candidates"
8585

8686
if [ -z "$found" ]; then
87-
# Re-run the single/last candidate with output shown, so the reason is visible rather than
88-
# swallowed -- "no candidate worked" is not an actionable message on its own.
89-
echo "==> No candidate authenticated. Reason from the most likely one:" >&2
90-
last=$(printf '%s\n' "$candidates" | tail -1)
91-
CLOUDFLARE_API_TOKEN="$last" CLOUDFLARE_ACCOUNT_ID="$account" \
92-
node tools/cf-verify-token.mjs || true
87+
echo "==> No candidate authenticated." >&2
88+
echo >&2
89+
90+
# Describe what was actually on the clipboard, by shape only. "No candidate worked" is not
91+
# actionable; "you pasted a 64-hex string, which is an R2 secret, not an API token" is. The most
92+
# common cause of landing here is copying the wrong page.
93+
echo " What was found (shapes only -- no values):" >&2
94+
local_n=0
95+
while IFS= read -r c; do
96+
[ -n "$c" ] || continue
97+
local_n=$((local_n + 1))
98+
len=$(printf '%s' "$c" | wc -c | tr -d ' ')
99+
note=""
100+
if printf '%s' "$c" | grep -qE '^[0-9a-f]{64}$'; then
101+
note=" <- 64 hex: this is an R2 SECRET ACCESS KEY, not an API token"
102+
elif printf '%s' "$c" | grep -qE '^[0-9a-f]{32}$'; then
103+
note=" <- 32 hex: this is an account/zone id or an R2 Access Key ID"
104+
elif printf '%s' "$c" | grep -qE '^cf[a-z]{2}_'; then
105+
note=" <- has a Cloudflare token prefix, but Cloudflare rejects it (revoked? mistyped?)"
106+
else
107+
note=" <- token-shaped, but Cloudflare does not recognise it"
108+
fi
109+
echo " candidate ${local_n}: length=${len}${note}" >&2
110+
done <<< "$candidates"
111+
112+
echo >&2
113+
echo " If you see R2 shapes above, you copied the R2 token page. The Workers token comes" >&2
114+
echo " from a different place: My Profile -> API Tokens -> Create Token -> Custom token." >&2
115+
echo " Its page says \"API token created!\" and shows one long value." >&2
93116
die "nothing was written"
94117
fi
95118

0 commit comments

Comments
 (0)