juanfont/headscale · warning

either --id or --prefix must be provided: %w

Error message

either --id or --prefix must be provided: %w

What it means

Validation error from apiKeyIDOrPrefix: the user invoked an API-key subcommand (expire/delete) with neither --id nor --prefix. At least one identifier is required because the server routes the request to a specific key. It wraps the sentinel errMissingParameter so callers can test for it with errors.Is.

Source

Thrown at cmd/headscale/cli/api_key.go:122

		}

		if resp.StatusCode() != http.StatusOK {
			return apiError(resp.StatusCode(), resp.ApplicationproblemJSONDefault)
		}

		return printOutput(cmd, resp.JSON200.ApiKey, resp.JSON200.ApiKey)
	}),
}

// apiKeyIDOrPrefix reads --id and --prefix from cmd and validates that
// exactly one is provided.
func apiKeyIDOrPrefix(cmd *cobra.Command) (uint64, string, error) {
	id, _ := cmd.Flags().GetUint64("id")
	prefix, _ := cmd.Flags().GetString("prefix")

	switch {
	case id == 0 && prefix == "":
		return 0, "", fmt.Errorf("either --id or --prefix must be provided: %w", errMissingParameter)
	case id != 0 && prefix != "":
		return 0, "", fmt.Errorf("only one of --id or --prefix can be provided: %w", errMissingParameter)
	}

	return id, prefix, nil
}

var expireAPIKeyCmd = &cobra.Command{
	Use:     cmdExpire,
	Short:   "Expire an ApiKey",
	Aliases: []string{"revoke", aliasExp, "e"},
	RunE: clientRunE(func(ctx context.Context, client *clientv1.ClientWithResponses, cmd *cobra.Command, args []string) error {
		id, prefix, err := apiKeyIDOrPrefix(cmd)
		if err != nil {
			return err
		}

		body := clientv1.ExpireApiKeyJSONRequestBody{}

View on GitHub (pinned to 565fd254d0)

Solutions

  1. Pass exactly one of --id <n> or --prefix <prefix>
  2. Find valid values first with 'headscale apikeys list'
  3. For scripts, capture the id/prefix from the create or list output programmatically

Example fix

# before
headscale apikeys expire

# after
headscale apikeys expire --prefix abcdef1234
Defensive patterns

Strategy: validation

Validate before calling

id, _ := cmd.Flags().GetUint64("id")
prefix, _ := cmd.Flags().GetString("prefix")
if id == 0 && prefix == "" {
	return fmt.Errorf("pass --id or --prefix; see 'headscale apikeys list'")
}

Try / catch

if err := cmd.Execute(); err != nil {
	if errors.Is(err, cli.ErrMissingParameter) { /* print usage hint and exit 2 */ }
}

Prevention

When it happens

Trigger: Running 'headscale apikeys expire' or 'headscale apikeys delete' with no --id and no --prefix flags (id==0 and prefix=="").

Common situations: Scripts written for an older CLI that took a positional key argument; users assuming the command operates on the most recent key; typos in flag names so both flags read as unset.

Related errors


AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15). Data as JSON: /api/errors/d90d09147aa0d0f6. Report an issue: GitHub.