router-for-me/CLIProxyAPI · error

home jwt target address is invalid

Error message

home jwt target address is invalid

What it means

Final claim check in parseHomeJWTClaims: the target address is invalid because the ip claim is empty/whitespace OR the port claim is <= 0. Together these tell the enrolled client where to reach the home coordinator for mTLS.

Source

Thrown at internal/home/certificate.go:107

		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) == "" {
		return claims, fmt.Errorf("home jwt enrollment_secret is required")
	}
	if strings.TrimSpace(claims.IP) == "" || claims.Port <= 0 {
		return claims, fmt.Errorf("home jwt target address is invalid")
	}
	return claims, nil
}

func decodeJWTPart(part string) ([]byte, error) {
	if decoded, errDecode := base64.RawURLEncoding.DecodeString(part); errDecode == nil {
		return decoded, nil
	}
	return base64.URLEncoding.DecodeString(part)
}

func defaultCertificatePaths() (certificatePaths, error) {
	homeDir, errHome := os.UserHomeDir()
	if errHome != nil {
		return certificatePaths{}, errHome
	}
	dir := filepath.Join(homeDir, ".cli-proxy-api")
	return certificatePaths{

View on GitHub (pinned to 78f0c4079e)

Solutions

  1. Use a token whose payload has a non-empty ip and a positive port (e.g. "ip":"10.0.0.5","port":8443)
  2. If you control minting, log the claims (never the secret) at mint time to catch this early
  3. Check for a coordinator version/config regression if tokens previously worked

Example fix

// before (JWT payload)
{"ip":"","port":0, ...}

// after (JWT payload)
{"ip":"203.0.113.10","port":8443, ...}
Defensive patterns

Strategy: validation

Validate before calling

func targetAddressOK(payload []byte) bool {
    var c struct {
        IP   string `json:"ip"`
        Port int   `json:"port"`
    }
    return json.Unmarshal(payload, &c) == nil &&
        strings.TrimSpace(c.IP) != "" && c.Port > 0
}

Prevention

When it happens

Trigger: JWT payload has ip: "" (or missing, which decodes to empty) or port: 0 / negative — e.g. a token minted with a hostname in the wrong claim, or port defaulted to zero because the field was omitted.

Common situations: Coordinator config misbinding (address split incorrectly into ip/port), token built from a template missing the port, or port passed as a string that failed to unmarshal into the numeric claim.

Related errors


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