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

  1. Re-copy the entire token from `claude setup-token` output as one single-line selection, then verify length: `[ ${#TOKEN} -ge 80 ]`.
  2. Disable terminal line-wrapping interference by copying from a wider terminal or redirecting output to a file and copying from there.
  3. If storing in env/secrets, confirm the stored value survived intact (compare lengths before and after storage).
  4. 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

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


AI-assisted analysis of sipeed/picoclaw@49183d7e8d (2026-08-15). Data as JSON: /api/errors/78ea7ea1da6f2459. Report an issue: GitHub.