cli/cli · error

unable to delete GPG key %s: either the GPG key is not found

Error message

unable to delete GPG key %s: either the GPG key is not found or it is not owned by you

What it means

Thrown by gh gpg-key delete after it listed all GPG keys on the account and found none whose KeyID equals --key-id. The deletion endpoint needs the database ID, so a miss on the local lookup produces this combined not-found/not-yours message before any API mutation is attempted.

Source

Thrown at pkg/cmd/gpg-key/delete/delete.go:83

		return err
	}

	host, _ := cfg.Authentication().DefaultHost()
	gpgKeys, err := getGPGKeys(httpClient, host)
	if err != nil {
		return err
	}

	id := ""
	for _, gpgKey := range gpgKeys {
		if gpgKey.KeyID == opts.KeyID {
			id = strconv.FormatInt(gpgKey.ID, 10)
			break
		}
	}

	if id == "" {
		return fmt.Errorf("unable to delete GPG key %s: either the GPG key is not found or it is not owned by you", opts.KeyID)
	}

	if !opts.Confirmed {
		if err := opts.Prompter.ConfirmDeletion(opts.KeyID); err != nil {
			return err
		}
	}

	err = deleteGPGKey(httpClient, host, id)
	if err != nil {
		return err
	}

	if opts.IO.IsStdoutTTY() {
		cs := opts.IO.ColorScheme()
		fmt.Fprintf(opts.IO.Out, "%s GPG key %s deleted from your account\n", cs.SuccessIcon(), opts.KeyID)
	}

View on GitHub (pinned to 0eeec0b92e)

Solutions

  1. List your keys and copy the exact ID: `gh gpg-key list`.
  2. Confirm you are on the right host/account: `gh auth status`; switch with `gh auth switch`.
  3. If the key is already absent, no action is needed; the delete goal is already met.

Example fix

# before
gh gpg-key delete "4CAE 5D6F ..."   # fingerprint passed
# gh: unable to delete GPG key ...: either the GPG key is not found or it is not owned by you

# after
gh gpg-key list                      # shows KeyID 3AA5C34371567BD2
gh gpg-key delete 3AA5C34371567BD2
Defensive patterns

Strategy: validation

Validate before calling

// Resolve the key against the account list before deleting:
keys, err := getGPGKeys(httpClient, host)
if err != nil { return err }
found := false
for _, k := range keys {
	if k.KeyID == opts.KeyID { found = true; break }
}
if !found {
	// print available KeyIDs so the user can correct the argument
	return fmt.Errorf("key %s not in account; run `gh gpg-key list`", opts.KeyID)
}

Type guard

func keyExists(keys []gpgKey, keyID string) bool {
	for _, k := range keys {
		if k.KeyID == keyID { return true }
	}
	return false
}

Try / catch

if err := deleteRun(opts); err != nil {
	if strings.Contains(err.Error(), "unable to delete GPG key") {
		// run `gh gpg-key list`, compare KeyIDs exactly, retry or treat as already-deleted
	}
}

Prevention

When it happens

Trigger: `gh gpg-key delete ABC1234D` with a mistyped or wrong-case key ID, a key uploaded to a different account/host, or a key already removed. The comparison is against the short/long key IDs returned by the list API.

Common situations: Using the fingerprint instead of the key ID, using the key ID from a work account against a personal GH_HOST, or repeating a delete that already succeeded.

Related errors


AI-assisted analysis of cli/cli@0eeec0b92e (2026-08-15). Data as JSON: /api/errors/6345c8b3b38ae108. Report an issue: GitHub.