{"record":{"id":"29be74b1cede3265","repo":"juanfont/headscale","slug":"invalid-protocol-number","errorCode":null,"errorMessage":"invalid protocol number","messagePattern":"invalid protocol number","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"hscontrol/policy/v2/types.go","lineNumber":131,"sourceCode":"\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)\")\n\tErrAutogroupNotSupported       = errors.New(\"autogroup not supported in headscale\")\n\tErrAutogroupInternetSrc        = errors.New(\"autogroup:internet can only be used in ACL destinations\")\n\tErrAutogroupSelfSrc            = errors.New(\"\\\"autogroup:self\\\" not valid on the src side of a rule\")\n\tErrAutogroupNotSupportedACLSrc = errors.New(\"autogroup not supported for ACL sources\")\n\tErrAutogroupNotSupportedACLDst = errors.New(\"autogroup not supported for ACL destinations\")\n\tErrAutogroupDangerAllDst       = errors.New(\"cannot use autogroup:danger-all as a dst\")\n\tErrAutogroupNotSupportedSSHSrc = errors.New(\"autogroup not supported for SSH sources\")\n\tErrAutogroupNotSupportedSSHDst = errors.New(\"autogroup not supported for SSH destinations\")\n\tErrHostNotDefined              = errors.New(\"host not defined in policy\")\n\tErrSSHSourceAliasNotSupported  = errors.New(\"alias not supported for SSH source\")\n\tErrSSHDestAliasNotSupported    = errors.New(\"alias not supported for SSH destination\")\n\tErrUnknownField                = errors.New(\"unknown field\")\n\tErrProtocolNoSpecificPorts     = errors.New(\"protocol does not support specific ports\")\n\tErrTestEmptyAssertions         = errors.New(\"test entry must have at least one of \\\"accept\\\" or \\\"deny\\\"\")\n\tErrTestProtocolNotAllowed      = errors.New(\"test protocol must be tcp, udp, sctp, or empty\")\n\tErrTestDestinationMultiPort    = errors.New(\"test destination port must be a single port\")","sourceCodeStart":113,"sourceCodeEnd":149,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/hscontrol/policy/v2/types.go#L113-L149","documentation":"Returned by Protocol.validate (hscontrol/policy/v2/types.go:1775) when an ACL rule's \"proto\" value is neither a known protocol name (icmp, igmp, ipv4, ipinip, tcp, egp, igp, udp, gre, esp, ah, sctp, ipv6-icmp, fc) nor parseable as an integer protocol number. The error message reminds that the value must be a known name or a number 0-255.","triggerScenarios":"Policy with \"proto\": \"tcp/udp\" (protocols are one per rule), \"proto\": \"http\" (http is not an IP protocol), \"proto\": \"TLS\", or any non-numeric non-name string. Fires during ACL unmarshalling at policy load.","commonSituations":"Confusing application-layer protocols (http, https, ssh-as-proto) with IP protocols; trying to express multiple protocols in one rule; copy-paste from other firewall syntax.","solutions":["Use an IANA protocol name from the supported set (tcp, udp, icmp, sctp, gre, esp, ah, ...)","Or use the numeric IP protocol number (0-255), e.g. 47 for GRE","For multiple protocols, write one ACL rule per protocol, or omit \"proto\" entirely to match all"],"exampleFix":"// before\n{\"action\": \"accept\", \"proto\": \"http\", \"src\": [\"group:dev\"], \"dst\": [\"tag:web:80\"]}\n\n// after\n{\"action\": \"accept\", \"proto\": \"tcp\", \"src\": [\"group:dev\"], \"dst\": [\"tag:web:80\"]}","handlingStrategy":"validation","validationCode":"var knownProto = map[string]bool{\"icmp\": true, \"igmp\": true, \"ipv4\": true, \"ipinip\": true, \"tcp\": true, \"egp\": true, \"igp\": true, \"udp\": true, \"gre\": true, \"esp\": true, \"ah\": true, \"sctp\": true, \"ipv6-icmp\": true, \"fc\": true}\nfunc validProto(s string) bool {\n\tif knownProto[s] || s == \"\" {\n\t\treturn true\n\t}\n\tn, err := strconv.Atoi(s)\n\treturn err == nil && n >= 0 && n <= 255\n}","typeGuard":"func isInvalidProtocolNumber(err error) bool {\n\treturn errors.Is(err, policy.ErrInvalidProtocolNumber)\n}","tryCatchPattern":"if err := json.Unmarshal(b, &acl); err != nil {\n\tif errors.Is(err, policy.ErrInvalidProtocolNumber) {\n\t\treturn fmt.Errorf(\"proto must be an IANA name or 0-255: %w\", err)\n\t}\n\treturn err\n}","preventionTips":["One protocol per rule; duplicate the rule for tcp+udp","Use protocol names where available to avoid semantic mistakes","Remember http/https/ssh are ports, not IP protocols"],"tags":["policy","acl","protocol","validation"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}