semaphoreui/semaphore · error
error at keys[ ]
Error message
error at keys[%d]: %s
What it means
This error wraps a per-item failure from BackupFormat.Verify() while validating backup.Keys: each key object's Verify(backup) is called, and any returned error is re-wrapped as "error at keys[%d]: %s". It means the key entry at the given index in the backup file is invalid (missing fields, broken references to the project backup, etc.) and the backup cannot be restored until it is fixed.
Solutions
- Read the inner error after 'keys[i]:' — it names the exact key validation failure
- Open the backup file and fix or remove the key entry at the reported index
- Re-export the backup from the same Semaphore version instead of hand-editing
- Run backup.Meta/Keys through a JSON schema check before calling Restore
Example fix
// before
"keys": [{"name": ""}]
// after
"keys": [{"name": "deploy-key", "type": "ssh", "project_id": 0}] Defensive patterns
Strategy: validation
Validate before calling
for i, k := range backup.Keys {
if k == nil || k.Name == "" {
return fmt.Errorf("keys[%d]: missing name before restore", i)
}
}
if err := backup.Verify(); err != nil {
return err
} Type guard
func validKey(k *KeyBackup) bool { return k != nil && k.Name != "" } Try / catch
if err := backup.Verify(); err != nil {
var idxErr *IndexError
if errors.As(err, &idxErr) { /* inspect entry at idxErr.Index */ }
return fmt.Errorf("backup validation failed: %w", err)
} Prevention
- Always call backup.Verify() before Restore
- Never hand-edit backup JSON; re-export from the source instance
- Keep source and target Semaphore versions compatible
When it happens
Trigger: Calling BackupFormat.Verify() (directly or via project restore) where the key at backup.Keys[i] fails its own Verify(backup) — e.g. missing name/type, duplicate key name, or references to entities not present in the backup.
Common situations: Hand-edited or partially exported backup.json; backups generated by a different Semaphore version whose key schema changed; truncated or merged backups missing referenced entities.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- error at repositories
- error at inventories
- item does not exist
- item does not exist
- repository does not exist in repositories[].name
AI-assisted analysis of semaphoreui/semaphore@1774ccb71a (2026-09-07).
Data as JSON: /api/errors/ffcf9469e7928c5f.
Report an issue: GitHub.
Appendix: source
Thrown at services/project/restore.go:553
func (backup *BackupFormat) Verify() error {
for i, o := range backup.Environments {
if err := o.Verify(backup); err != nil {
return fmt.Errorf("error at environments[%d]: %s", i, err.Error())
}
}
for i, o := range backup.Views {
if err := o.Verify(backup); err != nil {
return fmt.Errorf("error at views[%d]: %s", i, err.Error())
}
}
for i, o := range backup.Schedules {
if err := o.Verify(backup); err != nil {
return fmt.Errorf("error at templates[%d]: %s", i, err.Error())
}
}
for i, o := range backup.Keys {
if err := o.Verify(backup); err != nil {
return fmt.Errorf("error at keys[%d]: %s", i, err.Error())
}
}
for i, o := range backup.Repositories {
if err := o.Verify(backup); err != nil {
return fmt.Errorf("error at repositories[%d]: %s", i, err.Error())
}
}
for i, o := range backup.Inventories {
if err := o.Verify(backup); err != nil {
return fmt.Errorf("error at inventories[%d]: %s", i, err.Error())
}
}
for i, o := range backup.SecretStorages {
if err := o.Verify(backup); err != nil {
return fmt.Errorf("error at secret storage[%d]: %s", i, err.Error())
}
}
for i, o := range backup.Templates {View on GitHub (pinned to 1774ccb71a)