{"record":{"id":"163bb0dbeb7b84a4","repo":"juanfont/headscale","slug":"auto-approving-routes-w","errorCode":null,"errorMessage":"auto approving routes: %w","messagePattern":"auto approving routes: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"hscontrol/auth.go","lineNumber":453,"sourceCode":"\t\treturn nil, nil //nolint:nilnil // intentional: no node to return when ephemeral deleted\n\t}\n\n\t// This is a bit of a back and forth, but we have a bit of a chicken and egg\n\t// dependency here.\n\t// Because the way the policy manager works, we need to have the node\n\t// in the database, then add it to the policy manager and then we can\n\t// approve the route. This means we get this dance where the node is\n\t// first added to the database, then we add it to the policy manager via\n\t// nodesChangedHook and then we can auto approve the routes.\n\t// As that only approves the struct object, we need to save it again and\n\t// ensure we send an update.\n\t// This works, but might be another good candidate for doing some sort of\n\t// eventbus.\n\t// TODO(kradalby): This needs to be ran as part of the batcher maybe?\n\t// now since we dont update the node/pol here anymore\n\troutesChange, err := h.state.AutoApproveRoutes(node)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"auto approving routes: %w\", err)\n\t}\n\n\t// Send both changes. Empty changes are ignored by Change().\n\th.Change(changed, routesChange)\n\n\tresp := &tailcfg.RegisterResponse{\n\t\tMachineAuthorized: true,\n\t\tNodeKeyExpired:    node.IsExpired(),\n\t\tUser:              node.Owner().TailscaleUser(),\n\t\tLogin:             node.Owner().TailscaleLogin(),\n\t}\n\n\tlog.Trace().\n\t\tCaller().\n\t\tInterface(\"reg.resp\", resp).\n\t\tInterface(\"reg.req\", req).\n\t\tEmbedObject(node).\n\t\tMsg(\"RegisterResponse\")","sourceCodeStart":435,"sourceCodeEnd":471,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/hscontrol/auth.go#L435-L471","documentation":"Wraps a failure of h.state.AutoApproveRoutes(node) at the end of registration with an auth key (hscontrol/auth.go:453). After the node is persisted and added to the policy manager, routes the node advertises and the policy allows are auto-approved; this error means that approval step (route matching plus a subsequent state save of the node) failed. Note the comment in the source: the node add and the route approval are two separate saves, so a failure here can leave the node registered but its routes unapproved.","triggerScenarios":"Registering a node that advertises subnet routes (--advertise-routes) with an autoApprovers policy entry, while the second state save fails: DB lock, connection drop, or policy manager inconsistency after the node was added.","commonSituations":"Subnet routers registering under load on SQLite; policy file changed concurrently with registration; DB transient failures during bulk router enrollment.","solutions":["Check whether the node itself registered (it likely did) and only route approval failed: `headscale nodes list` and `headscale routes list`.","Approve the routes manually: `headscale routes enable -r <route-id>` (or the corresponding route approve command).","Fix the underlying DB issue reported in the wrapped error (locks/connectivity) so future registrations auto-approve.","Retry registration if the node state is inconsistent; re-running with the same auth key policy re-attempts approval."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":"resp, err := h.handleRegister(req, mk)\nif err != nil && strings.Contains(err.Error(), \"auto approving routes\") {\n    // node registration itself likely succeeded: check `headscale routes list` and approve manually\n}","preventionTips":["After registering subnet routers, verify routes: `headscale routes list` and enable missed ones.","Keep autoApprovers policy stable during enrollment windows.","Remember the two-phase save: registration and route approval are separate writes; monitor both."],"tags":["routes","auto-approval","registration","database","policy"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}