router-for-me/CLIProxyAPI · error
home jwt is invalid
Error message
home jwt is invalid
What it means
Thrown by parseHomeJWTClaims in internal/home/certificate.go when the home enrollment JWT does not have exactly three dot-separated segments (header.payload.signature). It is a shape check performed before any decoding — the token is not a structurally valid JWT.
Source
Thrown at internal/home/certificate.go:85
Enabled: true,
NodeID: strings.TrimSpace(claims.CertificateID),
Host: strings.TrimSpace(claims.IP),
Port: claims.Port,
TLS: config.HomeTLSConfig{
Enable: true,
CACert: paths.CACert,
ClientCert: paths.ClientCert,
ClientKey: paths.ClientKey,
UseTargetServerName: true,
},
}, nil
}
func parseHomeJWTClaims(rawJWT string) (homeJWTClaims, error) {
var claims homeJWTClaims
parts := strings.Split(strings.TrimSpace(rawJWT), ".")
if len(parts) != 3 {
return claims, fmt.Errorf("home jwt is invalid")
}
payload, errDecode := decodeJWTPart(parts[1])
if errDecode != nil {
return claims, errDecode
}
if errUnmarshal := json.Unmarshal(payload, &claims); errUnmarshal != nil {
return claims, errUnmarshal
}
if strings.TrimSpace(claims.CertificateID) == "" {
return claims, fmt.Errorf("home jwt certificate_id is required")
}
if strings.TrimSpace(claims.ClusterID) == "" {
return claims, fmt.Errorf("home jwt cluster_id is required")
}
if normalizeFingerprint(claims.CAFingerprint) == "" {
return claims, fmt.Errorf("home jwt ca_fingerprint is required")
}
if strings.TrimSpace(claims.EnrollmentSecret) == "" {View on GitHub (pinned to 78f0c4079e)
Solutions
- Re-copy the full enrollment JWT; it must look like xxxxx.yyyyy.zzzzz with exactly two dots
- Verify the variable/argument carrying it was not truncated (echo ${#TOKEN} and compare with the source)
- Confirm you are passing the home enrollment token, not an API key or session token
Example fix
# before CLI_PROXY_HOME_TOKEN="eyJhbGciOiJFUzI1NiIsImtpZCI6" # truncated # after CLI_PROXY_HOME_TOKEN="eyJhbGciOiJFUzI1NiIs...J9.eyJjZXJ0aWZpY2F0ZV9pZCI6...In0.SIG"
Defensive patterns
Strategy: validation
Validate before calling
func looksLikeCompactJWT(s string) bool {
parts := strings.Split(strings.TrimSpace(s), ".")
return len(parts) == 3 && parts[0] != "" && parts[1] != "" && parts[2] != ""
} Prevention
- Check the token has exactly two dots before passing it to enrollment
- Store enrollment tokens in files or env vars verbatim; avoid shell line-wrapping
- Log token length (never content) when ingest fails to spot truncation
When it happens
Trigger: Passing a value that is not a compact JWS: a raw opaque token, a truncated/copied-incomplete string, a JWE (5 parts), or an empty/whitespace string with extra dots.
Common situations: Copy-pasting the enrollment token and losing the tail, environment-variable wrapping/truncation, passing an API key instead of the enrollment JWT, or shell quoting that splits the token.
Related errors
- home jwt certificate_id is required
- home jwt cluster_id is required
- home jwt ca_fingerprint is required
- home jwt enrollment_secret is required
- home jwt target address is invalid
AI-assisted analysis of router-for-me/CLIProxyAPI@78f0c4079e (2026-08-15).
Data as JSON: /api/errors/37a1617827905d6b.
Report an issue: GitHub.