{"record":{"id":"f710b9a75413d0cc","repo":"juanfont/headscale","slug":"w-d","errorCode":null,"errorMessage":"%w: %d","messagePattern":"%w: %d","errorType":"validation","errorClass":"ErrProtocolOutOfRange","httpStatus":null,"severity":"error","filePath":"hscontrol/policy/v2/types.go","lineNumber":1779,"sourceCode":"\tcase ProtocolNameWildcard:\n\t\t// Wildcard \"*\" is not allowed - Tailscale rejects it\n\t\treturn errUnknownProtocolWildcard\n\tdefault:\n\t\t// Try to parse as a numeric protocol number\n\t\tstr := string(*p)\n\n\t\t// Check for leading zeros (not allowed by Tailscale)\n\t\tif str == \"0\" || (len(str) > 1 && str[0] == '0') {\n\t\t\treturn fmt.Errorf(\"%w: %q\", ErrProtocolLeadingZero, str)\n\t\t}\n\n\t\tprotocolNumber, err := strconv.Atoi(str)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"%w: %q must be a known protocol name or valid protocol number 0-255\", ErrInvalidProtocolNumber, *p)\n\t\t}\n\n\t\tif protocolNumber < 0 || protocolNumber > 255 {\n\t\t\treturn fmt.Errorf(\"%w: %d\", ErrProtocolOutOfRange, protocolNumber)\n\t\t}\n\n\t\treturn nil\n\t}\n}\n\n// MarshalJSON implements JSON marshaling for [Protocol].\nfunc (p *Protocol) MarshalJSON() ([]byte, error) {\n\treturn json.Marshal(string(*p))\n}\n\n// Protocol constants matching the IANA numbers.\nconst (\n\tProtocolICMP     = 1   // Internet Control Message\n\tProtocolIGMP     = 2   // Internet Group Management\n\tProtocolIPv4     = 4   // IPv4 encapsulation\n\tProtocolTCP      = 6   // Transmission Control\n\tProtocolEGP      = 8   // Exterior Gateway Protocol","sourceCodeStart":1761,"sourceCodeEnd":1797,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/hscontrol/policy/v2/types.go#L1761-L1797","documentation":"The proto string parsed as an integer but fell outside 0-255 (ErrProtocolOutOfRange). IP protocol numbers are a single byte, so anything larger (or negative via a leading '-') is invalid.","triggerScenarios":"A proto value like \"256\", \"1000\", or \"-1\" — often a port number accidentally placed in the proto field.","commonSituations":"Swapping the proto and port fields when hand-editing rules; confusing IANA protocol numbers with port numbers.","solutions":["Correct the number to the intended IANA protocol (e.g. 6=tcp, 17=udp)","If the value was meant to be a port, move it into the ports list"],"exampleFix":"// before\n{\"proto\": \"443\", \"ports\": [\"tcp\"]}\n// after\n{\"proto\": \"tcp\", \"ports\": [\"443\"]}","handlingStrategy":"validation","validationCode":"func protocolInRange(s string) bool {\n\tn, err := strconv.Atoi(s)\n\treturn err == nil && n >= 0 && n <= 255\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep proto (IANA number 0-255) and ports (0-65535) fields straight","Prefer names for common protocols to avoid number mistakes"],"tags":["policy","protocol","range","validation"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}