juanfont/headscale · error

deleting api key: %w

Error message

deleting api key: %w

What it means

Transport error from 'headscale apikeys delete': the DELETE request (addressed by prefix in the URL path, possibly resolved from --id via apiKeyPrefixForID) failed at the HTTP layer before a response arrived. Note the delete-by-id path performs an extra list call first, so a failure here means the actual DELETE call failed, not the prefix lookup.

Source

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

	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
		}

		// The DELETE route addresses the key by its prefix in the path. When the
		// user deletes by --id we resolve the id to its (masked) prefix first,
		// since the path segment is required and a query-only id cannot be routed.
		if prefix == "" {
			prefix, err = apiKeyPrefixForID(ctx, client, id)
			if err != nil {
				return err
			}
		}

		resp, err := client.DeleteApiKeyWithResponse(ctx, prefix, &clientv1.DeleteApiKeyParams{})
		if err != nil {
			return fmt.Errorf("deleting api key: %w", err)
		}

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

		return printOutput(cmd, resp.JSON200, "Key deleted")
	}),
}

// apiKeyPrefixForID resolves an API key id to its display prefix by listing the
// keys. The DELETE endpoint addresses keys by prefix in the URL path, so a
// delete by --id needs the prefix; the returned masked prefix is accepted by
// the server's lookup.
func apiKeyPrefixForID(
	ctx context.Context,
	client *clientv1.ClientWithResponses,
	id uint64,

View on GitHub (pinned to 565fd254d0)

Solutions

  1. Verify connectivity ('headscale health')
  2. Confirm address/TLS config, then retry the delete
  3. If deleting by --id failed after the prefix lookup succeeded, re-run with --prefix directly to skip the extra list round trip
Defensive patterns

Strategy: retry

Validate before calling

// prefer prefix to skip the id->prefix resolution round trip
if prefix != "" { /* single DELETE call, fewer failure points */ }

Try / catch

if _, err := client.DeleteApiKeyWithResponse(ctx, prefix, params); err != nil {
	if isTransportError(err) { /* verify with list, then retry once */ }
}

Prevention

When it happens

Trigger: Deleting an API key while the server is unreachable or restarting; TLS/cert mismatch; context timeout on a slow link.

Common situations: Automation running deletes against a server mid-restart; CLI pointing at a stale address after a server migration; proxy interference with DELETE verbs.

Related errors


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