sipeed/picoclaw · error

reading token: %w

Error message

reading token: %w

What it means

LoginPasteToken (pkg/auth/token.go:17) failed while reading the pasted token: bufio.Scanner reported a hard error. The wrapped error distinguishes causes — most commonly bufio.ErrBufferTooLong when a single line exceeds the 64 KiB default scanner buffer, or an I/O error on the provided reader (broken pipe, closed stdin).

Source

Thrown at pkg/auth/token.go:17

package auth

import (
	"bufio"
	"fmt"
	"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`:")

View on GitHub (pinned to 49183d7e8d)

Solutions

  1. Check scanner.Err(): 'token too long' means the buffer limit — enlarge it with scanner.Buffer(buf, maxSize)
  2. Keep tokens under 64 KiB or feed them via a file/pipe: LoginPasteToken(provider, strings.NewReader(token)) programmatically
  3. If the reader is a pipe, verify the writer side stays open for the duration of the read
  4. Test with a small known token first to separate size issues from stream issues

Example fix

// before
scanner := bufio.NewScanner(r)

// after (allow long tokens)
scanner := bufio.NewScanner(r)
scanner.Buffer(make([]byte, 0, 64*1024), 1024*1024)
Defensive patterns

Strategy: validation

Validate before calling

// Pre-size the reader path: read via a scanner with a large buffer yourself
sc := bufio.NewScanner(r)
sc.Buffer(make([]byte, 0, 64*1024), 1024*1024)
if !sc.Scan() {
	return fmt.Errorf("no token line available")
}
// pass sc.Text() on, or pass a strings.NewReader to the library

Type guard

func isTokenReadError(err error) bool {
	return err != nil && strings.Contains(err.Error(), "reading token")
}

Try / catch

cred, err := auth.LoginPasteToken(provider, r)
if err != nil && isTokenReadError(err) {
	if errors.Is(err, bufio.ErrBufferTooLong) {
		// token exceeded 64 KiB scanner limit
		return fmt.Errorf("token too long for interactive paste: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: Calling LoginPasteToken with r = os.Stdin (or another reader) where the line exceeds bufio.MaxScanTokenSize (65536 bytes), the reader returns a read error, or the input stream errors before a newline.

Common situations: Pasting a very long session token/JWT chain (>64 KiB) into the interactive prompt; piping a file that dies mid-read; automation passing a closed pipe as the reader; terminal multiplexers mangling huge pastes.

Related errors


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