{"record":{"id":"1617b73f91bd5f22","repo":"juanfont/headscale","slug":"invalid-prefix","errorCode":null,"errorMessage":"invalid prefix","messagePattern":"invalid prefix","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"hscontrol/policy/v2/types.go","lineNumber":115,"sourceCode":"// today. Each entry maps to the tracking issue an operator can follow. The\n// caps are accepted by Tailscale SaaS, but delivering them via headscale\n// without the matching server-side machinery would be misleading — nodes\n// would advertise a feature that does not work. Reject at policy load and\n// point operators at the issue.\nvar nodeAttrUnsupportedCaps = map[tailcfg.NodeCapability]string{\n\ttailcfg.NodeAttrFunnel: \"https://github.com/juanfont/headscale/issues/2527\",\n}\n\n// Policy validation errors.\nvar (\n\tErrInvalidUsername             = errors.New(\"username must contain @\")\n\tErrUserNotFound                = errors.New(\"user not found\")\n\tErrMultipleUsersFound          = errors.New(\"multiple users found\")\n\tErrInvalidGroupFormat          = errors.New(\"group must start with 'group:'\")\n\tErrInvalidTagFormat            = errors.New(\"tag must start with 'tag:'\")\n\tErrInvalidHostname             = errors.New(\"invalid hostname\")\n\tErrHostResolve                 = errors.New(\"error resolving host\")\n\tErrInvalidPrefix               = errors.New(\"invalid prefix\")\n\tErrInvalidAutogroup            = errors.New(\"invalid autogroup\")\n\tErrUnknownAutogroup            = errors.New(\"unknown autogroup\")\n\tErrHostportMissingColon        = errors.New(\"hostport must contain a colon\")\n\tErrTypeNotSupported            = errors.New(\"type not supported\")\n\tErrInvalidAlias                = errors.New(\"invalid alias format\")\n\tErrInvalidAutoApprover         = errors.New(\"invalid auto approver format\")\n\tErrInvalidOwner                = errors.New(\"invalid owner format\")\n\tErrGroupNotDefined             = errors.New(\"group not defined in policy\")\n\tErrInvalidGroupMember          = errors.New(\"invalid group member type\")\n\tErrGroupValueNotArray          = errors.New(\"group value must be an array of users\")\n\tErrInvalidHostIP               = errors.New(\"hostname contains invalid IP address\")\n\tErrTagNotDefined               = errors.New(\"tag not found\")\n\tErrAutoApproverNotAlias        = errors.New(\"auto approver is not an alias\")\n\tErrInvalidACLAction            = errors.New(\"invalid ACL action\")\n\tErrInvalidSSHAction            = errors.New(\"invalid SSH action\")\n\tErrInvalidProtocolNumber       = errors.New(\"invalid protocol number\")\n\tErrProtocolLeadingZero         = errors.New(\"leading 0 not permitted in protocol number\")\n\tErrProtocolOutOfRange          = errors.New(\"protocol number out of range (0-255)\")","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/hscontrol/policy/v2/types.go#L97-L133","documentation":"Prefix.Validate (hscontrol/policy/v2/types.go:647-652) wraps netip.Prefix.IsValid; any address/prefix token that Go's net/netip considers invalid (bad octets, malformed mask, non-IP text where an IP was required) is rejected with this sentinel including the raw string.","triggerScenarios":"A hosts-map value or alias that parses as a prefix but is invalid — e.g. \"10.0.0/32\" (incomplete address), \"10.0.0.0/33\" (mask out of range), \"100.100.100.256/32\", or a bare malformed string like \"10.0.0.0/24/24\". Fails at parse or when Host.resolve validates the mapped prefix (types.go:632).","commonSituations":"Hand-editing CIDRs and dropping an octet; copying prefixes with unicode dashes; typo in netmask bits; pasting host entries with trailing characters.","solutions":["Correct the CIDR to a valid dotted-quad plus legal mask length","Validate prefixes with 'ipcalc' or equivalent before pasting","Use /32 for single addresses instead of bare IPs where required"],"exampleFix":"// before\n{\"hosts\": {\"example-host\": \"10.0.0/32\"}}\n// after\n{\"hosts\": {\"example-host\": \"10.0.0.1/32\"}}","handlingStrategy":"validation","validationCode":"if _, err := netip.ParsePrefix(cidr); err != nil {\n    return fmt.Errorf(\"invalid prefix %q: %w\", cidr, err)\n}","typeGuard":"func isValidPrefix(s string) bool { _, err := netip.ParsePrefix(s); return err == nil }","tryCatchPattern":"if errors.Is(err, policy.ErrInvalidPrefix) {\n    // the wrapped value shows the bad CIDR; correct octets/mask\n}","preventionTips":["Always write full dotted-quad CIDRs","Parse-validate generated prefixes with netip before emitting","Use /32 for single hosts"],"tags":["headscale","policy","cidr","prefix","validation"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}