cloudflare/cloudflared · error

backend returned invalid network %s

Error message

backend returned invalid network %s

What it means

This error is thrown by CIDR.UnmarshalJSON when the Cloudflare API backend returns a JSON string that net.ParseCIDR parses successfully but yields a nil network — meaning the backend produced a network value that cannot be represented as a CIDR. It indicates the backend response does not conform to the expected IP route schema. The error is a defensive invariant check after successful parsing.

Source

Thrown at cfapi/ip_route.go:60

	json, err := json.Marshal(str)
	if err != nil {
		return nil, errors.Wrap(err, "error serializing CIDR into JSON")
	}
	return json, nil
}

// UnmarshalJSON parses a JSON string into net.IPNet
func (c *CIDR) UnmarshalJSON(data []byte) error {
	var s string
	if err := json.Unmarshal(data, &s); err != nil {
		return errors.Wrap(err, "error parsing cidr string")
	}
	_, network, err := net.ParseCIDR(s)
	if err != nil {
		return errors.Wrap(err, "error parsing invalid network from backend")
	}
	if network == nil {
		return fmt.Errorf("backend returned invalid network %s", s)
	}
	*c = CIDR(*network)
	return nil
}

// NewRoute has all the parameters necessary to add a new route to the table.
type NewRoute struct {
	Network  net.IPNet
	TunnelID uuid.UUID
	Comment  string
	// Optional field. If unset, backend will assume the default vnet for the account.
	VNetID *uuid.UUID
}

// MarshalJSON handles fields with non-JSON types (e.g. net.IPNet).
func (r NewRoute) MarshalJSON() ([]byte, error) {
	return json.Marshal(&struct {
		Network  string     `json:"network"`

View on GitHub (pinned to 2253eeeb25)

Solutions

  1. Verify the exact JSON value the backend returned for the network field (log the raw response body before unmarshalling).
  2. Update cloudflared/cfapi types to match the current Cloudflare API schema for IP routes.
  3. If the backend can return an empty value, pre-filter route entries or add a custom UnmarshalJSON path that skips blank strings.
  4. Report the malformed backend response to Cloudflare support with the request ID if the API genuinely returned a bad network.

Example fix

// before
type Route struct {
	Network cfapi.CIDR `json:"network"`
}
// after
type Route struct {
	Network cfapi.CIDR `json:"network"`
}
// guard before decode:
var raw struct{ Network string `json:"network"` }
_ = json.Unmarshal(body, &raw)
if _, _, err := net.ParseCIDR(raw.Network); err != nil || raw.Network == "" { /* skip or handle */ }
Defensive patterns

Strategy: validation

Validate before calling

func validCIDR(s string) bool {
	if s == "" { return false }
	_, n, err := net.ParseCIDR(s)
	return err == nil && n != nil
}
if !validCIDR(raw.Network) { /* skip entry or handle before json.Unmarshal into cfapi.CIDR */ }

Type guard

func isParsedCIDR(n *net.IPNet) bool { return n != nil }

Prevention

When it happens

Trigger: Unmarshalling a JSON payload (e.g. from the /ip_routes API) into cfapi.CIDR where the string parses via net.ParseCIDR without error yet returns a nil *net.IPNet, which in practice means an empty or malformed value slipped past the parser.

Common situations: Cloudflare API schema changes or bugs returning unexpected route fields; stale SDK types used against a newer/older API; mocked or replayed test fixtures with empty network strings.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


AI-assisted analysis of cloudflare/cloudflared@2253eeeb25 (2026-09-06). Data as JSON: /api/errors/e08a0c069c78e7bb. Report an issue: GitHub.