semaphoreui/semaphore · error

SSHKey does not exist in keys[].Name

Error message

SSHKey does not exist in keys[].Name

What it means

BackupInventory.Verify checks that an inventory's optional SSHKey reference names an existing entry in the backup's keys[] (access keys). If the named key is absent, verification fails with this error before restore, catching dangling key references early.

Solutions

  1. Add an access-key entry with that name to keys[] in the backup.
  2. Point inventory.ssh_key at an existing keys[].name entry.
  3. Set ssh_key to null if the inventory does not need an SSH key.
  4. Run Verify on the whole backup and fix all dangling key references before restoring.

Example fix

// before
"ssh_key": "deploy-key", "keys": []
// after
"keys": [{"name": "deploy-key", ...}]
Defensive patterns

Strategy: validation

Validate before calling

func inventorySSHKeyExists(b BackupFormat) error {
    for _, inv := range b.Inventories {
        if inv.SSHKey != nil && getEntryByName[BackupAccessKey](*inv.SSHKey, b.Keys) == nil {
            return fmt.Errorf("inventory %q references missing ssh_key %q", inv.Name, *inv.SSHKey)
        }
    }
    return nil
}

Try / catch

if err := backup.Verify(); err != nil {
    if strings.Contains(err.Error(), "SSHKey does not exist") {
        // add the key or null the ssh_key reference, then retry
    }
    return err
}

Prevention

When it happens

Trigger: Calling BackupFormat.Verify (or restore preflight) on a backup where inventory.ssh_key names an access key missing from keys[].name — key deleted, renamed, or omitted from the export.

Common situations: Partial backups that skipped access keys; renamed keys after export; hand-edited backups; inventories copied between projects referencing keys from another project.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of semaphoreui/semaphore@1774ccb71a (2026-09-07). Data as JSON: /api/errors/f6e473419f632ded. Report an issue: GitHub.

Appendix: source

Thrown at services/project/restore.go:174

		}
		key.SourceStorageID = &sourceStorage.ID
	}

	newKey, err := b.store.CreateAccessKey(key)

	if err != nil {
		return err
	}
	b.keys = append(b.keys, newKey)
	return nil
}

func (e BackupInventory) Verify(backup *BackupFormat) error {
	if err := verifyDuplicate[BackupInventory](e.Name, backup.Inventories); err != nil {
		return err
	}
	if e.SSHKey != nil && getEntryByName[BackupAccessKey](e.SSHKey, backup.Keys) == nil {
		return fmt.Errorf("SSHKey does not exist in keys[].Name")
	}
	if e.BecomeKey != nil && getEntryByName[BackupAccessKey](e.BecomeKey, backup.Keys) == nil {
		return fmt.Errorf("BecomeKey does not exist in keys[].Name")
	}
	return nil
}

func (e BackupInventory) Restore(b *BackupDB) error {
	var SSHKeyID *int
	if e.SSHKey == nil {
		SSHKeyID = nil
	} else if k := findEntityByName[db.AccessKey](e.SSHKey, b.keys); k == nil {
		SSHKeyID = nil
	} else {
		SSHKeyID = &((*k).ID)
	}
	var BecomeKeyID *int
	if e.BecomeKey == nil {

View on GitHub (pinned to 1774ccb71a)