{"record":{"id":"fb5bc6c332305230","repo":"slackhq/nebula","slug":"calculated-remotes-entry-has-invalid-type-t","errorCode":null,"errorMessage":"calculated_remotes entry has invalid type: %T","messagePattern":"calculated_remotes entry has invalid type: %T","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"calculated_remote.go","lineNumber":111,"sourceCode":"\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"config `%s` has invalid CIDR: %s\", k, rawCIDR)\n\t\t}\n\n\t\tentry, err := newCalculatedRemotesListFromConfig(cidr, rawValue)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"config '%s.%s': %w\", k, rawCIDR, err)\n\t\t}\n\n\t\tcalculatedRemotes.Insert(cidr, entry)\n\t}\n\n\treturn calculatedRemotes, nil\n}\n\nfunc newCalculatedRemotesListFromConfig(cidr netip.Prefix, raw any) ([]*calculatedRemote, error) {\n\trawList, ok := raw.([]any)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"calculated_remotes entry has invalid type: %T\", raw)\n\t}\n\n\tvar l []*calculatedRemote\n\tfor _, e := range rawList {\n\t\tc, err := newCalculatedRemotesEntryFromConfig(cidr, e)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"calculated_remotes entry: %w\", err)\n\t\t}\n\t\tl = append(l, c)\n\t}\n\n\treturn l, nil\n}\n\nfunc newCalculatedRemotesEntryFromConfig(cidr netip.Prefix, raw any) (*calculatedRemote, error) {\n\trawMap, ok := raw.(map[string]any)\n\tif !ok {\n\t\treturn nil, fmt.Errorf(\"invalid type: %T\", raw)","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/calculated_remote.go#L93-L129","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Wrap the entry in a YAML list: add `- ` before the entry under the CIDR key","Check the %T in the message: map[string]interface {} usually means a missing list dash","Keep every CIDR's value a list even if it contains only one entry"],"exampleFix":"// before\nlighthouse:\n  calculated_remotes:\n    10.0.42.0/24:\n      mask: 10.0.0.0/8\n      port: 4242\n// after\nlighthouse:\n  calculated_remotes:\n    10.0.42.0/24:\n      - mask: 10.0.0.0/8\n        port: 4242","handlingStrategy":"type-guard","validationCode":"v := rawMap[cidrKey]\nif _, ok := v.([]any); !ok {\n\treturn fmt.Errorf(\"value for %s must be a list of entries\", cidrKey)\n}","typeGuard":"func isEntryList(v any) bool {\n\t_, ok := v.([]any)\n\treturn ok\n}","tryCatchPattern":"tbl, err := NewCalculatedRemotesFromConfig(c, k)\nif err != nil {\n\tif strings.Contains(err.Error(), \"entry has invalid type\") {\n\t\treturn fmt.Errorf(\"each CIDR must map to a list of entries: %w\", err)\n\t}\n\treturn err\n}","preventionTips":["Always use YAML list syntax (`- `) for entries even when there is only one","Never map a CIDR key directly to a single map or scalar","Run a YAML lint/schema check on the config before deploying"],"tags":["nebula","config","type-error","yaml","calculated-remotes"],"backgroundTag":"config-type-mismatch","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}