chenhg5/cc-connect · critical

yuanbao: generate nonce: %w

Error message

yuanbao: generate nonce: %w

What it means

Thrown by fetchToken when crypto/rand.Read fails to fill the 16-byte nonce buffer during token acquisition. This means the OS entropy source is unavailable or the cryptographic RNG errored — on modern Linux this is nearly always a sign of a serious system-level problem (e.g. exhausted/degraded entropy, restricted /dev/urandom, seccomp blocking getrandom).

Source

Thrown at platform/yuanbao/sign.go:126

	s := now.Format("2006-01-02T15:04:05+08:00")
	return s
}

func fetchToken(appKey, appSecret, apiDomain, routeEnv string) (*tokenData, error) {
	if apiDomain == "" {
		apiDomain = defaultAPIDomain
	}
	urlStr := strings.TrimRight(apiDomain, "/") + tokenPath
	client := &http.Client{Timeout: httpTimeout}
	var lastErr error

	for attempt := 0; attempt <= maxRetries; attempt++ {
		if attempt > 0 {
			time.Sleep(retryDelay)
		}
		nonceBytes := make([]byte, 16)
		if _, err := rand.Read(nonceBytes); err != nil {
			lastErr = fmt.Errorf("yuanbao: generate nonce: %w", err)
			continue
		}
		nonce := hex.EncodeToString(nonceBytes)
		timestamp := buildTimestamp()
		signature := computeSignature(nonce, timestamp, appKey, appSecret)

		payload := map[string]string{
			"app_key": appKey, "nonce": nonce,
			"signature": signature, "timestamp": timestamp,
		}
		body, _ := json.Marshal(payload)

		req, err := http.NewRequest("POST", urlStr, strings.NewReader(string(body)))
		if err != nil {
			lastErr = fmt.Errorf("yuanbao: create request: %w", err)
			continue
		}
		req.Header.Set("Content-Type", "application/json")

View on GitHub (pinned to 4000b2338a)

Solutions

  1. Inspect the wrapped error from lastErr/logs to identify the syscall failure (getrandom vs /dev/urandom) and fix the container/seccomp policy to allow getrandom.
  2. Verify /dev/urandom is present and readable in the deployment environment (ls -l /dev/urandom; test with dd if=/dev/urandom of=/dev/null bs=16 count=1).
  3. Upgrade the base image/kernel if running on an old or minimal system with broken RNG support.
  4. Check that the host's entropy/CRNG initialized correctly (dmesg for 'random: crng init done').
  5. Rely on the existing retry/backoff: if the failure is transient the loop retries up to maxRetries; surface the final error if all attempts fail.

Example fix

// before
nonceBytes := make([]byte, 16)
if _, err := rand.Read(nonceBytes); err != nil {
    lastErr = fmt.Errorf("yuanbao: generate nonce: %w", err)
    continue
}
// after (host-side fix: allow getrandom in the sandbox)
// Docker: drop the seccomp restriction or add "getrandom" to the allowlist
// docker run --security-opt seccomp=allowed-syscalls.json ...
Defensive patterns

Strategy: retry

Validate before calling

func entropyAvailable() error {
    b := make([]byte, 16)
    if _, err := rand.Read(b); err != nil {
        return fmt.Errorf("entropy source unavailable: %w", err)
    }
    return nil
} // call at startup, before attempting token fetch

Try / catch

token, err := fetchToken(ctx, cfg)
if err != nil {
    if strings.Contains(err.Error(), "generate nonce") {
        slog.Error("crypto RNG failed; environment problem", "err", err)
        // do NOT retry locally forever — fail health check, alert operator
        return fmt.Errorf("token fetch blocked by RNG failure: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: rand.Read returns a non-nil error inside the token fetch retry loop (up to maxRetries attempts with retryDelay backoff); lastErr holds the wrapped cause and the loop continues to the next attempt. Callers: getToken, VerifyCredentials.

Common situations: Containers/seccomp profiles blocking the getrandom syscall, stripped-down VMs or embedded systems with broken /dev/urandom, or a compromised/misconfigured CSPRNG in exotic environments. Also seen in sandboxes that stub crypto/rand.

Related errors


AI-assisted analysis of chenhg5/cc-connect@4000b2338a (2026-09-06). Data as JSON: /api/errors/f05e18b3df2a9d81. Report an issue: GitHub.