{"record":{"id":"10061c91c13df197","repo":"juanfont/headscale","slug":"internal-error","errorCode":null,"errorMessage":"Internal error","messagePattern":"Internal error","errorType":"http","errorClass":"HTTPError","httpStatus":500,"severity":"error","filePath":"hscontrol/noise.go","lineNumber":531,"sourceCode":"\n// sshActionHoldAndDelegate creates a new auth session bound to the\n// (src, dst) pair and returns a [tailcfg.SSHAction.HoldAndDelegate] action that directs the\n// client to authenticate.\nfunc (ns *noiseServer) sshActionHoldAndDelegate(\n\treqLog zerolog.Logger,\n\taction *tailcfg.SSHAction,\n\tsrcNodeID, dstNodeID types.NodeID,\n) (*tailcfg.SSHAction, error) {\n\tholdURL, err := url.Parse(\n\t\tns.headscale.cfg.ServerURL +\n\t\t\t\"/machine/ssh/action/$SRC_NODE_ID/to/$DST_NODE_ID\" +\n\t\t\t\"?local_user=$LOCAL_USER\",\n\t)\n\tif err != nil {\n\t\treturn nil, NewHTTPError(\n\t\t\thttp.StatusInternalServerError,\n\t\t\t\"Internal error\",\n\t\t\tfmt.Errorf(\"parsing SSH action URL: %w\", err),\n\t\t)\n\t}\n\n\tauthID, err := types.NewAuthID()\n\tif err != nil {\n\t\treturn nil, NewHTTPError(\n\t\t\thttp.StatusInternalServerError,\n\t\t\t\"Internal error\",\n\t\t\tfmt.Errorf(\"generating auth ID: %w\", err),\n\t\t)\n\t}\n\n\tns.headscale.state.SetAuthCacheEntry(\n\t\tauthID,\n\t\ttypes.NewSSHCheckAuthRequest(srcNodeID, dstNodeID),\n\t)\n\n\tauthURL := ns.headscale.authProvider.AuthURL(authID)","sourceCodeStart":513,"sourceCodeEnd":549,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/hscontrol/noise.go#L513-L549","documentation":"Returned by sshActionHoldAndDelegate when url.Parse fails on the internally constructed hold URL (ServerURL + /machine/ssh/action/... with $ placeholders). Because the path is a fixed constant, failure can only come from a malformed ServerURL configuration that makes the combined URL unparseable.","triggerScenarios":"cfg.ServerURL containing characters that break URL parsing when concatenated (control characters, invalid percent-encoding).","commonSituations":"HEADCSCALE_SERVER_URL pasted with hidden control characters or an invalid scheme; a config typo introduced during deployment.","solutions":["Print and inspect the configured server_url for stray characters","Set server_url to a clean absolute URL like https://headscale.example.com","Restart headscale after fixing the config"],"exampleFix":"# before\nserver_url: https://headscale.example.com\\x0b\n\n# after\nserver_url: https://headscale.example.com","handlingStrategy":"validation","validationCode":"if u, err := url.Parse(cfg.ServerURL); err != nil || !u.IsAbs() {\n    return errors.New(\"server_url must be a valid absolute URL\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate server_url at startup before serving","Keep config values free of control characters — generate configs, do not paste through terminals that can inject them"],"tags":["ssh","config","url","internal-error"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}