{"record":{"id":"53b7fa8dd6e045cc","repo":"juanfont/headscale","slug":"name-or-identifier-flag-is-required","errorCode":null,"errorMessage":"--name or --identifier flag is required","messagePattern":"--name or --identifier flag is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"cmd/headscale/cli/users.go","lineNumber":20,"sourceCode":"\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strconv\"\n\n\tclientv1 \"github.com/juanfont/headscale/gen/client/v1\"\n\t\"github.com/juanfont/headscale/hscontrol/util\"\n\t\"github.com/juanfont/headscale/hscontrol/util/zlog/zf\"\n\t\"github.com/rs/zerolog/log\"\n\t\"github.com/spf13/cobra\"\n)\n\n// CLI user errors.\nvar (\n\terrFlagRequired       = errors.New(\"--name or --identifier flag is required\")\n\terrMultipleUsersMatch = errors.New(\"multiple users match query, specify an ID\")\n)\n\nfunc usernameAndIDFlag(cmd *cobra.Command) {\n\tcmd.Flags().Int64P(\"identifier\", \"i\", -1, \"User identifier (ID)\")\n\tcmd.Flags().StringP(\"name\", \"n\", \"\", \"Username\")\n}\n\n// usernameAndIDFromFlag returns the username and ID from the flags of the command.\nfunc usernameAndIDFromFlag(cmd *cobra.Command) (uint64, string, error) {\n\tusername, _ := cmd.Flags().GetString(\"name\")\n\n\tidentifier, _ := cmd.Flags().GetInt64(\"identifier\")\n\tif username == \"\" && identifier < 0 {\n\t\treturn 0, \"\", errFlagRequired\n\t}\n\n\t// Normalise unset/negative identifiers to 0 so the uint64","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/cmd/headscale/cli/users.go#L2-L38","documentation":"HTTP 405 from PingResponseHandler, the in-noise endpoint clients call (HEAD) to prove connectivity after receiving a tailcfg.PingRequest. The authentication is the unguessable ping ID, so any non-HEAD verb is rejected outright before the ID is even inspected.","triggerScenarios":"Sending GET or POST to the ping-response path inside the noise tunnel; curl without -I/--head; a custom client implementing the ping responder with the wrong method.","commonSituations":"Manually testing the endpoint with curl (default GET) while debugging derp/connectivity; client code that answers PingRequest with GET.","solutions":["Use HEAD: curl -I 'https://host/ts2021/ping-response?id=<id>' (inside the noise tunnel, clients do this automatically).","In client code, answer tailcfg.PingRequest with an http.HEAD request carrying the ?id= query parameter.","Do not probe this path with GET/POST — there is no GET fallback by design."],"exampleFix":"# before (405 method not allowed)\ncurl 'http://host/.../ping-response?id=abc'\n\n# after\ncurl -I 'http://host/.../ping-response?id=abc'","handlingStrategy":"validation","validationCode":"// Always issue HEAD for ping responses.\nif method != http.MethodHead {\n    return fmt.Errorf(\"ping-response endpoint requires HEAD, got %s\", method)\n}\nreq, _ := http.NewRequest(http.MethodHead, pingURL, nil)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use curl -I when hand-testing HEAD-only endpoints.","In client implementations, read tailcfg.PingRequest handling docs and answer with HEAD exactly once."],"tags":["http","method-not-allowed","ping","noise"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}