semaphoreui/semaphore · error
roles[].role does not exist in roles[].name
Error message
roles[].role does not exist in roles[].name
What it means
For non-global template role entries, BackupTemplate.Restore resolves roles[].role as a project-local role name via findEntityByName[db.Role] against BackupDB.roles (project roles restored earlier). This error is thrown when no restored project role matches the name, so the template role permission cannot be created.
Solutions
- Add the missing role to roles[] in the backup with an exactly matching name
- Fix roles[].role to the name of an existing project role in the backup
- Remove the template role entry if the permission is no longer needed
- Re-run backup export so role references are regenerated consistently
Example fix
// before
{"roles": [{"name": "developer"}], "templates": [{"roles": [{"role": "dev", "isGlobal": false}]}]}
// after
{"roles": [{"name": "developer"}], "templates": [{"roles": [{"role": "developer", "isGlobal": false}]}]} Defensive patterns
Strategy: validation
Validate before calling
roleNames := map[string]bool{}
for _, r := range backup.Roles {
roleNames[r.Name] = true
}
for i, t := range backup.Templates {
for _, tr := range t.Roles {
if !tr.IsGlobal && !roleNames[tr.Role] {
return fmt.Errorf("templates[%d].role %q not in roles[]", i, tr.Role)
}
}
} Try / catch
if err := backup.Verify(); err != nil {
if strings.Contains(err.Error(), "roles[].role does not exist in roles[].name") {
return fmt.Errorf("backup references a missing project role: %w", err)
}
return err
} Prevention
- Run Verify() before Restore
- Keep roles[] complete whenever templates[] with role permissions are exported
- Avoid renaming project roles between backup and restore
- Validate hand-merged backup files for cross-references
When it happens
Trigger: Restoring a backup whose templates[].roles[].role (isGlobal=false) does not match any roles[].name in the backup, or whose role entry was not restored before the template step.
Common situations: Role deleted or renamed in the backup file; partial restore skipping the roles section; name/case mismatch after manual edits; backup merged from different projects.
Understand the failure class
Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.
Related errors
- repository does not exist in repositories[].name
- inventory does not exist in inventories[].name
- vault_key does not exist in keys[].name
- vaults[].vaultKey does not exist in keys[].name
- view does not exist in views[].name
AI-assisted analysis of semaphoreui/semaphore@1774ccb71a (2026-09-07).
Data as JSON: /api/errors/6ec929ecf8f78178.
Report an issue: GitHub.
Appendix: source
Thrown at services/project/restore.go:385
if err != nil {
return fmt.Errorf("global role does not exist: %s", role.Role)
}
_, err = b.store.CreateTemplateRole(db.TemplateRolePerm{
TemplateID: newTemplate.ID,
RoleSlug: r.Slug,
ProjectID: b.meta.ID,
Permissions: role.Permissions,
})
if err != nil {
return err
}
continue
}
if k := findEntityByName[db.Role](&role.Role, b.roles); k == nil {
return fmt.Errorf("roles[].role does not exist in roles[].name")
} else {
_, err = b.store.CreateTemplateRole(db.TemplateRolePerm{
TemplateID: newTemplate.ID,
RoleSlug: k.Slug,
ProjectID: b.meta.ID,
Permissions: role.Permissions,
})
if err != nil {
return err
}
}
}
}
return nil
}
func (e BackupIntegration) Restore(b *BackupDB) error {View on GitHub (pinned to 1774ccb71a)