router-for-me/CLIProxyAPI · critical

failed to generate code verifier: %w

Error message

failed to generate code verifier: %w

What it means

GeneratePKCECodes wraps the failure of generateCodeVerifier, which draws 96 bytes from crypto/rand and base64url-encodes them into a 128-char RFC 7636 verifier. The only real failure mode is the wrapped rand.Read error (see error 189); there is no user input involved. If this fires, the host's CSPRNG is unavailable.

Source

Thrown at internal/auth/claude/pkce.go:25

	"crypto/rand"
	"crypto/sha256"
	"encoding/base64"
	"fmt"
)

// GeneratePKCECodes generates a PKCE code verifier and challenge pair
// following RFC 7636 specifications for OAuth 2.0 PKCE extension.
// This provides additional security for the OAuth flow by ensuring that
// only the client that initiated the request can exchange the authorization code.
//
// Returns:
//   - *PKCECodes: A struct containing the code verifier and challenge
//   - error: An error if the generation fails, nil otherwise
func GeneratePKCECodes() (*PKCECodes, error) {
	// Generate code verifier: 43-128 characters, URL-safe
	codeVerifier, err := generateCodeVerifier()
	if err != nil {
		return nil, fmt.Errorf("failed to generate code verifier: %w", err)
	}

	// Generate code challenge using S256 method
	codeChallenge := generateCodeChallenge(codeVerifier)

	return &PKCECodes{
		CodeVerifier:  codeVerifier,
		CodeChallenge: codeChallenge,
	}, nil
}

// generateCodeVerifier creates a cryptographically random string
// of 128 characters using URL-safe base64 encoding
func generateCodeVerifier() (string, error) {
	// Generate 96 random bytes (will result in 128 base64 characters)
	bytes := make([]byte, 96)
	_, err := rand.Read(bytes)
	if err != nil {

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Check the wrapped error: on Linux it is usually getrandom blocking — wait for the CRNG to initialize (cat /proc/sys/kernel/random/entropy_avail) and retry login.
  2. Upgrade the kernel past 3.17 / use a standard runtime instead of a stubbed sandbox.
  3. In containers, ensure the host has booted long enough to seed the CRNG before starting the login flow.
Defensive patterns

Strategy: retry

Validate before calling

// probe CSPRNG health before starting login
if _, err := cryptoRandRead(32); err != nil {
    return fmt.Errorf("host entropy unavailable, retry after boot: %w", err)
}

Try / catch

codes, err := claude.GeneratePKCECodes()
if err != nil {
    if strings.Contains(err.Error(), "random") { // environment issue: wait and retry once
        time.Sleep(5 * time.Second)
        codes, err = claude.GeneratePKCECodes()
    }
}

Prevention

When it happens

Trigger: Calling GeneratePKCECodes() (i.e. starting any Claude OAuth login) on a system where crypto/rand.Read returns an error — typically a blocked entropy source at early boot or a broken getrandom(2) in constrained sandboxes/gVisor.

Common situations: Freshly booted VMs/containers where the kernel CRNG is not yet initialized; very old kernels (pre-3.17) without getrandom; minimal VMs (gVisor, some WASI runtimes) with stubbed crypto syscalls; extremely rare in normal servers.

Related errors


AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15). Data as JSON: /api/errors/e2b361c8d2f5cfd8. Report an issue: GitHub.