slackhq/nebula · error

calculated_remotes entry has invalid type: %T

Error message

calculated_remotes entry has invalid type: %T

What it means

newCalculatedRemotesListFromConfig expects each CIDR's value in the calculated_remotes map to be a list ([]any) of entry maps. If the value is anything else — a single map instead of a list, a string, a scalar — it throws this error naming the actual Go type.

Source

Thrown at calculated_remote.go:111

		if err != nil {
			return nil, fmt.Errorf("config `%s` has invalid CIDR: %s", k, rawCIDR)
		}

		entry, err := newCalculatedRemotesListFromConfig(cidr, rawValue)
		if err != nil {
			return nil, fmt.Errorf("config '%s.%s': %w", k, rawCIDR, err)
		}

		calculatedRemotes.Insert(cidr, entry)
	}

	return calculatedRemotes, nil
}

func newCalculatedRemotesListFromConfig(cidr netip.Prefix, raw any) ([]*calculatedRemote, error) {
	rawList, ok := raw.([]any)
	if !ok {
		return nil, fmt.Errorf("calculated_remotes entry has invalid type: %T", raw)
	}

	var l []*calculatedRemote
	for _, e := range rawList {
		c, err := newCalculatedRemotesEntryFromConfig(cidr, e)
		if err != nil {
			return nil, fmt.Errorf("calculated_remotes entry: %w", err)
		}
		l = append(l, c)
	}

	return l, nil
}

func newCalculatedRemotesEntryFromConfig(cidr netip.Prefix, raw any) (*calculatedRemote, error) {
	rawMap, ok := raw.(map[string]any)
	if !ok {
		return nil, fmt.Errorf("invalid type: %T", raw)

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Wrap the entry in a YAML list: add `- ` before the entry under the CIDR key
  2. Check the %T in the message: map[string]interface {} usually means a missing list dash
  3. Keep every CIDR's value a list even if it contains only one entry

Example fix

// before
lighthouse:
  calculated_remotes:
    10.0.42.0/24:
      mask: 10.0.0.0/8
      port: 4242
// after
lighthouse:
  calculated_remotes:
    10.0.42.0/24:
      - mask: 10.0.0.0/8
        port: 4242
Defensive patterns

Strategy: type-guard

Validate before calling

v := rawMap[cidrKey]
if _, ok := v.([]any); !ok {
	return fmt.Errorf("value for %s must be a list of entries", cidrKey)
}

Type guard

func isEntryList(v any) bool {
	_, ok := v.([]any)
	return ok
}

Try / catch

tbl, err := NewCalculatedRemotesFromConfig(c, k)
if err != nil {
	if strings.Contains(err.Error(), "entry has invalid type") {
		return fmt.Errorf("each CIDR must map to a list of entries: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: A calculated_remotes CIDR key maps directly to one entry map `{mask: ..., port: ...}` without wrapping it in a list, or the value is a scalar/string due to YAML parsing.

Common situations: Users writing a single entry without the `- ` list syntax in YAML, or flow-style maps that collapse the list; also configs converted from other tools that allow single objects.

Related errors


AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03). Data as JSON: /api/errors/fb5bc6c332305230. Report an issue: GitHub.