sipeed/picoclaw · error
invalid setup token: too short (expected at least 80 charact
Error message
invalid setup token: too short (expected at least 80 characters)
What it means
The token passed the prefix check but is shorter than 80 characters, and real sk-ant-oat01- setup tokens are always at least 80 chars. This guard exists to catch truncated pastes before an opaque HTTP 401 from the API later. Only the total length is checked; no other structure is validated.
Source
Thrown at pkg/auth/token.go:53
fmt.Println("Paste your setup token from `claude setup-token`:")
fmt.Print("> ")
scanner := bufio.NewScanner(r)
if !scanner.Scan() {
if err := scanner.Err(); err != nil {
return nil, fmt.Errorf("reading token: %w", err)
}
return nil, fmt.Errorf("no input received")
}
token := strings.TrimSpace(scanner.Text())
if !strings.HasPrefix(token, "sk-ant-oat01-") {
return nil, fmt.Errorf("invalid setup token: expected prefix sk-ant-oat01-")
}
if len(token) < 80 {
return nil, fmt.Errorf("invalid setup token: too short (expected at least 80 characters)")
}
return &AuthCredential{
AccessToken: token,
Provider: "anthropic",
AuthMethod: "oauth",
}, nil
}
func providerDisplayName(provider string) string {
switch provider {
case "anthropic":
return "console.anthropic.com"
case "openai":
return "platform.openai.com"
default:
return provider
}View on GitHub (pinned to 49183d7e8d)
Solutions
- Re-copy the entire token from `claude setup-token` output as one single-line selection, then verify length: `[ ${#TOKEN} -ge 80 ]`.
- Disable terminal line-wrapping interference by copying from a wider terminal or redirecting output to a file and copying from there.
- If storing in env/secrets, confirm the stored value survived intact (compare lengths before and after storage).
- Retry the login flow with the full token.
Example fix
// before
// user pasted "sk-ant-oat01-abc123" (23 chars) -> "too short" error
// after - validate before calling, fail with actionable message
if len(strings.TrimSpace(token)) < 80 {
return fmt.Errorf("token looks truncated (%d chars, need >= 80); re-copy the full token", len(token))
}
cred, err := auth.LoginSetupToken(strings.NewReader(token)) Defensive patterns
Strategy: validation
Validate before calling
func isCompleteSetupToken(s string) bool {
s = strings.TrimSpace(s)
return strings.HasPrefix(s, "sk-ant-oat01-") && len(s) >= 80
}
if !isCompleteSetupToken(token) {
return fmt.Errorf("token truncated (%d chars, need >= 80); re-copy", len(token))
} Type guard
func isCompleteSetupToken(s string) bool {
s = strings.TrimSpace(s)
return strings.HasPrefix(s, "sk-ant-oat01-") && len(s) >= 80
} Try / catch
if _, err := auth.LoginSetupToken(r); err != nil {
if strings.Contains(err.Error(), "too short") {
return errors.New("token was cut off; widen the terminal, re-copy the single full line, and retry")
}
return err
} Prevention
- Copy setup tokens from unwrapped output (redirect to a file, copy from the file).
- Verify length client-side: len(token) >= 80 before calling.
- Prefer secret files/env over manual paste for automation.
When it happens
Trigger: Pasting only the first line/wrapped fragment of a token that was line-wrapped by a terminal; clipboard truncation; hand-typing a prefix plus partial body; shell variable storing a cut-off value.
Common situations: Terminal wraps long tokens across lines and the user copies just one line; tmux/screen copy-mode grabbing a partial region; secret managers clipping long values; pasting with a middle-click selection that stopped early.
Related errors
- invalid setup token: expected prefix sk-ant-oat01-
- no models available
- failed to get WeCom QR code: response missing scode or auth_
- WeCom QR scan succeeded but bot credentials are missing
- invalid WeCom QR generate URL: %w
AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15).
Data as JSON: /api/errors/78ea7ea1da6f2459.
Report an issue: GitHub.