{"record":{"id":"12bf1f99de7418d7","repo":"juanfont/headscale","slug":"route-is-not-available-on-node","errorCode":null,"errorMessage":"route is not available on node","messagePattern":"route is not available on node","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"hscontrol/db/node.go","lineNumber":45,"sourceCode":"\t// defaultTestNodePrefix is the default hostname prefix for nodes created in tests.\n\tdefaultTestNodePrefix = \"testnode\"\n)\n\n// ErrNodeNameNotUnique is returned when a node name is not unique.\nvar ErrNodeNameNotUnique = errors.New(\"node name is not unique\")\n\n// preloadNode returns a session that eager-loads a node's AuthKey, the\n// AuthKey's User, and the node's User.\nfunc preloadNode(tx *gorm.DB) *gorm.DB {\n\treturn tx.\n\t\tPreload(\"AuthKey\").\n\t\tPreload(\"AuthKey.User\").\n\t\tPreload(\"User\")\n}\n\nvar (\n\tErrNodeNotFound                  = errors.New(\"node not found\")\n\tErrNodeRouteIsNotAvailable       = errors.New(\"route is not available on node\")\n\tErrNodeNotFoundRegistrationCache = errors.New(\n\t\t\"node not found in registration cache\",\n\t)\n\tErrCouldNotConvertNodeInterface = errors.New(\"failed to convert node interface\")\n)\n\n// ListPeers returns peers of node, regardless of any Policy or if the node is expired.\n// If no peer IDs are given, all peers are returned.\n// If at least one peer ID is given, only these peer nodes will be returned.\nfunc (hsdb *HSDatabase) ListPeers(nodeID types.NodeID, peerIDs ...types.NodeID) (types.Nodes, error) {\n\treturn ListPeers(hsdb.DB, nodeID, peerIDs...)\n}\n\n// ListPeers returns peers of node, regardless of any Policy or if the node is expired.\n// If no peer IDs are given, all peers are returned.\n// If at least one peer ID is given, only these peer nodes will be returned.\nfunc ListPeers(tx *gorm.DB, nodeID types.NodeID, peerIDs ...types.NodeID) (types.Nodes, error) {\n\tnodes := types.Nodes{}","sourceCodeStart":27,"sourceCodeEnd":63,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/hscontrol/db/node.go#L27-L63","documentation":"Sentinel in hscontrol/db/node.go returned by EnableRoute/DisableRoute-style helpers when asked to toggle a route that the node does not currently advertise. Routes must appear in the node's Hostinfo advertised routes before they can be enabled or disabled as approved subnet routes.","triggerScenarios":"Calling `headscale routes enable` with a route/prefix the node has never advertised via `tailscale up --advertise-routes=...`; enabling by route ID that belongs to another node; node changed its advertised routes so the old prefix no longer exists.","commonSituations":"Approving a route typo'd in the CLI; the node dropped the advertisement (rebooted without --advertise-routes) and an automation still tries to approve the old prefix.","solutions":["Run `headscale routes list` to see routes actually advertised, and enable by the exact prefix/ID shown","On the node, re-run `tailscale set --advertise-routes=<prefix>` so the route is advertised, wait for it to appear, then enable","Fix automation scripts to look up route IDs dynamically instead of hardcoding them"],"exampleFix":"# before (route not advertised by node)\nheadscale routes enable --route 5\n\n# after\n# on the node:\ntailscale set --advertise-routes=10.42.0.0/24\n# on the server:\nheadscale routes list\nheadscale routes enable --route <id-from-list>","handlingStrategy":"validation","validationCode":"// confirm the node advertises the prefix before enabling it\nnode, _ := hsdb.GetNodeByID(nodeID)\nfor _, r := range node.Hostinfo().RoutableIPs {\n    if r == wantedPrefix { /* safe to enable */ }\n}","typeGuard":null,"tryCatchPattern":"if err := hsdb.EnableRoute(tx, nodeID, routeID); err != nil {\n    if errors.Is(err, db.ErrNodeRouteIsNotAvailable) {\n        return fmt.Errorf(\"node %d does not advertise this route; run `tailscale set --advertise-routes=%s` first\", nodeID, prefix)\n    }\n    return err\n}","preventionTips":["Always enable routes from the IDs shown by `headscale routes list`","Provision advertise-routes on nodes before approval automation runs","Re-check advertised routes after node reboots/reinstalls"],"tags":["routes","subnet","node","headscale"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}