router-for-me/CLIProxyAPI · error

private_key base64 payload empty

Error message

private_key base64 payload empty

What it means

From rebuildPEM after the BEGIN/END markers were located, but the text between them yields no base64 characters after filterBase64 strips whitespace and invalid characters (keyutil.go:137-141). The PEM envelope exists while the actual key payload is empty.

Source

Thrown at internal/auth/vertex/keyutil.go:140

	return nil, fmt.Errorf("private_key uses unsupported format")
}

func rebuildPEM(raw string) (string, error) {
	kind := "PRIVATE KEY"
	if strings.Contains(raw, "RSA PRIVATE KEY") {
		kind = "RSA PRIVATE KEY"
	}
	header := "-----BEGIN " + kind + "-----"
	footer := "-----END " + kind + "-----"
	start := strings.Index(raw, header)
	end := strings.Index(raw, footer)
	if start < 0 || end <= start {
		return "", fmt.Errorf("missing pem markers")
	}
	body := raw[start+len(header) : end]
	payload := filterBase64(body)
	if payload == "" {
		return "", fmt.Errorf("private_key base64 payload empty")
	}
	der, err := base64.StdEncoding.DecodeString(payload)
	if err != nil {
		return "", fmt.Errorf("private_key base64 decode failed: %w", err)
	}
	block := &pem.Block{Type: kind, Bytes: der}
	return string(pem.EncodeToMemory(block)), nil
}

func filterBase64(s string) string {
	var b strings.Builder
	for _, r := range s {
		switch {
		case r >= 'A' && r <= 'Z':
			b.WriteRune(r)
		case r >= 'a' && r <= 'z':
			b.WriteRune(r)
		case r >= '0' && r <= '9':

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Check that the secret value is not a placeholder; fetch the real key material from GCP
  2. Inspect the region between the BEGIN/END lines: jq -r .private_key sa.json | sed -n '2,3p' should show base64, not '***'
  3. Re-download and redeploy the unmodified service account JSON

Example fix

# before
"private_key": "-----BEGIN PRIVATE KEY-----\n***REDACTED***\n-----END PRIVATE KEY-----"
# after
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQ...(real base64)...\n-----END PRIVATE KEY-----"
Defensive patterns

Strategy: validation

Validate before calling

body := pkBetweenMarkers(pk)
if len(strings.Map(func(r rune) rune {
    if isBase64Rune(r) { return r }
    return -1
}, body)) == 0 {
    return fmt.Errorf("PEM body contains no base64 key material (redacted?)")
}

Prevention

When it happens

Trigger: A PEM block containing only comments or an empty body; base64 body replaced by placeholder text like '<redacted>' or '***'; whitespace-only body between valid-looking markers.

Common situations: Sanitized/redacted credential templates deployed by mistake; secret managers substituting placeholders when access is denied; manual template editing that deletes the body but leaves headers.

Related errors


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