{"record":{"id":"d94fc275ce8aa0b2","repo":"juanfont/headscale","slug":"only-one-of-id-or-prefix-can-be-provided-w","errorCode":null,"errorMessage":"only one of --id or --prefix can be provided: %w","messagePattern":"only one of --id or --prefix can be provided: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"cmd/headscale/cli/api_key.go","lineNumber":124,"sourceCode":"\t\tif resp.StatusCode() != http.StatusOK {\n\t\t\treturn apiError(resp.StatusCode(), resp.ApplicationproblemJSONDefault)\n\t\t}\n\n\t\treturn printOutput(cmd, resp.JSON200.ApiKey, resp.JSON200.ApiKey)\n\t}),\n}\n\n// apiKeyIDOrPrefix reads --id and --prefix from cmd and validates that\n// exactly one is provided.\nfunc apiKeyIDOrPrefix(cmd *cobra.Command) (uint64, string, error) {\n\tid, _ := cmd.Flags().GetUint64(\"id\")\n\tprefix, _ := cmd.Flags().GetString(\"prefix\")\n\n\tswitch {\n\tcase id == 0 && prefix == \"\":\n\t\treturn 0, \"\", fmt.Errorf(\"either --id or --prefix must be provided: %w\", errMissingParameter)\n\tcase id != 0 && prefix != \"\":\n\t\treturn 0, \"\", fmt.Errorf(\"only one of --id or --prefix can be provided: %w\", errMissingParameter)\n\t}\n\n\treturn id, prefix, nil\n}\n\nvar expireAPIKeyCmd = &cobra.Command{\n\tUse:     cmdExpire,\n\tShort:   \"Expire an ApiKey\",\n\tAliases: []string{\"revoke\", aliasExp, \"e\"},\n\tRunE: clientRunE(func(ctx context.Context, client *clientv1.ClientWithResponses, cmd *cobra.Command, args []string) error {\n\t\tid, prefix, err := apiKeyIDOrPrefix(cmd)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tbody := clientv1.ExpireApiKeyJSONRequestBody{}\n\n\t\tif id != 0 {","sourceCodeStart":106,"sourceCodeEnd":142,"githubUrl":"https://github.com/juanfont/headscale/blob/565fd254d06c4c7f9a8cad1714a43445c79ba420/cmd/headscale/cli/api_key.go#L106-L142","documentation":"Validation error from apiKeyIDOrPrefix: both --id and --prefix were supplied for an API-key subcommand (expire/delete). The API key must be addressed by exactly one identifier; providing both is ambiguous and rejected before any network call. Wraps errMissingParameter for errors.Is checks.","triggerScenarios":"Running 'headscale apikeys expire --id 3 --prefix abcdef1234' or the delete equivalent, where id!=0 and prefix!=\"\" simultaneously.","commonSituations":"Copy-pasted command lines where a previous key's flags accumulate; shell scripts looping over both id and prefix lists; users unaware the flags are mutually exclusive.","solutions":["Remove one of the two flags — use --prefix for stable scripting, --id for interactive use","Check the command line construction in scripts that template both values in","Use 'headscale apikeys list' to decide which identifier is most convenient"],"exampleFix":"# before\nheadscale apikeys delete --id 3 --prefix abcdef1234\n\n# after\nheadscale apikeys delete --prefix abcdef1234","handlingStrategy":"validation","validationCode":"if id != 0 && prefix != \"\" {\n\treturn fmt.Errorf(\"choose exactly one of --id or --prefix\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Build CLI invocations from a single identifier variable","Add a preflight argument check in wrapper scripts"],"tags":["cli","validation","flags","go"],"backgroundTag":null,"analyzedSha":"565fd254d06c4c7f9a8cad1714a43445c79ba420","analyzedAt":"2026-08-15T13:12:30.133Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}