router-for-me/CLIProxyAPI · error
home certificate request failed
Error message
home certificate request failed
What it means
Returned by the certificate-request exchange in internal/home/certificate.go: the client sent 'CERTIFICATE REQUEST <id> <secret> <csr>' over the RESP connection and received a JSON response with OK=false. The home server explicitly rejected the enrollment — the transport worked but the request was denied.
Source
Thrown at internal/home/certificate.go:330
}
defer func() {
_ = conn.Close()
}()
if deadline, ok := dialCtx.Deadline(); ok {
_ = conn.SetDeadline(deadline)
}
if _, errWrite := conn.Write(encodeRESPArray("CERTIFICATE", "REQUEST", claims.CertificateID, claims.EnrollmentSecret, string(csrPEM))); errWrite != nil {
return response, errWrite
}
raw, errRead := readRESPBulk(bufio.NewReader(conn))
if errRead != nil {
return response, errRead
}
if errUnmarshal := json.Unmarshal(raw, &response); errUnmarshal != nil {
return response, errUnmarshal
}
if !response.OK {
return response, fmt.Errorf("home certificate request failed")
}
return response, nil
}
func encodeRESPArray(args ...string) []byte {
var buf bytes.Buffer
buf.WriteString("*")
buf.WriteString(strconv.Itoa(len(args)))
buf.WriteString("\r\n")
for _, arg := range args {
buf.WriteString("$")
buf.WriteString(strconv.Itoa(len(arg)))
buf.WriteString("\r\n")
buf.WriteString(arg)
buf.WriteString("\r\n")
}
return buf.Bytes()
}View on GitHub (pinned to 78f0c4079e)
Solutions
- Inspect the response JSON (log it before this error is returned) for the server's reason string
- Regenerate/obtain a fresh enrollment secret and retry with the same certificate ID
- If the ID is taken, choose a new certificate ID or have the admin revoke the old entry first
- Verify server-side enrollment logs for the denial cause
Example fix
// before
if !response.OK {
return response, fmt.Errorf("home certificate request failed")
}
// after (capture the server reason for diagnosis)
if !response.OK {
return response, fmt.Errorf("home certificate request failed: ok=false error=%q", response.Error)
} Defensive patterns
Strategy: retry
Try / catch
resp, err := requestCertificate(ctx, csrPEM)
if err != nil {
if strings.Contains(err.Error(), "home certificate request failed") && resp.Error != "" {
log.Errorf("enrollment denied by server: %s", resp.Error)
}
// retry only for transient causes (expired-then-refreshed secret), never for wrong-secret loops
} Prevention
- Treat enrollment secrets as single-use: fetch a fresh one for each attempt
- Log the full JSON response before returning the generic failure so denials are diagnosable
- Use stable, unique certificate IDs per node to avoid duplicate-ID rejections
When it happens
Trigger: Enrollment secret wrong or expired; certificate ID already enrolled or revoked; CSR CommonName mismatch; server-side policy rejecting the request. The JSON response body often carries a reason field worth inspecting.
Common situations: Re-running enrollment with a one-time secret already consumed; secret rotated between generation and use; clock skew causing secret expiry; duplicate node ID joining the cluster.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- home certificate request returned nil
- certificate id is required
- %s
- home certificate request returned unsupported resp prefix %q
- home jwt is invalid
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/c1dabf2598bc08a4.
Report an issue: GitHub.