semaphoreui/semaphore · error
is duplicate
Error message
%s is duplicate
What it means
verifyDuplicate counts how many items in a backup entity list share the given name and fails if the name appears more than once (n > 2 counts the scan; more than one matching entry means duplication). Backup.Verify calls it to guarantee names are unique within each entity collection so name-based cross-references resolve unambiguously during restore.
Solutions
- Deduplicate the offending array in the backup JSON so each name appears exactly once (keeping the newest entry).
- Rename duplicates to unique names and update all references (e.g. inventory.ssh_key) to the new name.
- Re-export the backup after fixing uniqueness constraints at the source.
- Run Verify before Restore and fix all reported duplicate names in one pass.
Example fix
// before
"secret_storage": [{"name": "aws"}, {"name": "aws"}]
// after
"secret_storage": [{"name": "aws"}, {"name": "aws-eu"}] Defensive patterns
Strategy: validation
Validate before calling
func hasDuplicates[T interface{ GetName() string }](items []T) bool {
seen := map[string]bool{}
for _, it := range items {
if seen[it.GetName()] { return true }
seen[it.GetName()] = true
}
return false
}
// run over keys, inventories, templates, repositories, secret_storages before Verify Try / catch
if err := backup.Verify(); err != nil {
if strings.Contains(err.Error(), "is duplicate") {
// deduplicate the named entity in the backup JSON
}
return err
} Prevention
- Deduplicate exports before merging backups from multiple sources.
- Enforce name uniqueness at the source database level.
- Always run Verify before Restore in automation.
When it happens
Trigger: Calling BackupFormat.Verify (BackupSecretStorage.Verify and siblings) on a backup whose entity arrays (e.g. secret_storage, keys, inventories) contain two or more entries with the same name.
Common situations: Backups merged from multiple exports or environments; manual concatenation of JSON arrays; database with non-unique names restored from a legacy system; duplicated blocks from a bad copy-paste edit.
Related errors
- SSHKey does not exist in keys[].Name
- BecomeKey does not exist in keys[].Name
- secret does not belong to this environment
- name can not be empty
- missing secret
AI-assisted analysis of semaphoreui/semaphore@1774ccb71a (2026-09-07).
Data as JSON: /api/errors/81cdb40d2002f77c.
Report an issue: GitHub.
Appendix: source
Thrown at services/project/restore.go:30
if name == nil {
return nil
}
for _, o := range items {
if o.GetName() == *name {
return &o
}
}
return nil
}
func verifyDuplicate[T BackupEntry](name string, items []T) error {
n := 0
for _, o := range items {
if o.GetName() == name {
n++
}
if n > 2 {
return fmt.Errorf("%s is duplicate", name)
}
}
return nil
}
func (e BackupSecretStorage) Verify(backup *BackupFormat) error {
return verifyDuplicate[BackupSecretStorage](e.Name, backup.SecretStorages)
}
func (e BackupSecretStorage) Restore(b *BackupDB) error {
st := e.SecretStorage
st.ProjectID = b.meta.ID
newStorage, err := b.store.CreateSecretStorage(st)
if err != nil {
return err
}
b.secretStorages = append(b.secretStorages, newStorage)
return nilView on GitHub (pinned to 1774ccb71a)