sipeed/picoclaw · warning

token cannot be empty

Error message

token cannot be empty

What it means

LoginPasteToken (pkg/auth/token.go:24) received a line but it was empty after TrimSpace — the user pressed Enter on a blank line or pasted only whitespace. The library rejects it because an empty AccessToken would produce a useless credential.

Source

Thrown at pkg/auth/token.go:24

	"io"
	"strings"
)

func LoginPasteToken(provider string, r io.Reader) (*AuthCredential, error) {
	fmt.Printf("Paste your API key or session token from %s:\n", providerDisplayName(provider))
	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 token == "" {
		return nil, fmt.Errorf("token cannot be empty")
	}

	return &AuthCredential{
		AccessToken: token,
		Provider:    provider,
		AuthMethod:  "token",
	}, nil
}

func LoginSetupToken(r io.Reader) (*AuthCredential, error) {
	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)
		}

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Paste the actual key/token and press Enter — the prompt expects one non-blank line
  2. If scripting, verify the variable is non-empty before wiring it: strings.NewReader(strings.TrimSpace(token))
  3. Trim the clipboard content manually if it may contain leading/trailing whitespace (the function already trims, so pure whitespace means the clipboard itself was blank)
  4. Check for trailing newlines breaking a pasted multiline value — only the first line is read

Example fix

// before
cred, err := auth.LoginPasteToken(provider, os.Stdin)

// after (guard before prompting in scripted use)
token := strings.TrimSpace(os.Getenv("MY_TOKEN"))
if token == "" {
	return fmt.Errorf("MY_TOKEN is empty; set it before login")
}
cred, err := auth.LoginPasteToken(provider, strings.NewReader(token))
Defensive patterns

Strategy: validation

Validate before calling

// Normalize and reject blank input before it reaches the prompt logic
raw := strings.TrimSpace(suppliedToken)
if raw == "" {
	return fmt.Errorf("token value is empty; copy the key before pasting")
}
cred, err := auth.LoginPasteToken(provider, strings.NewReader(raw))

Type guard

func isEmptyTokenError(err error) bool {
	return err != nil && strings.Contains(err.Error(), "token cannot be empty")
}

Try / catch

cred, err := auth.LoginPasteToken(provider, r)
if err != nil && isEmptyTokenError(err) {
	// harmless user slip: re-prompt instead of failing
	cred, err = auth.LoginPasteToken(provider, r)
}

Prevention

When it happens

Trigger: At the 'Paste your API key or session token' prompt: pressing Enter immediately, pasting spaces/newlines only, or piping a whitespace-only string as the reader input.

Common situations: User unsure what to paste and pressing Enter to 'skip'; clipboard containing whitespace or a failed copy; scripted input accidentally passing ' ' or a blank variable; shell history expansion producing an empty line.

Related errors


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