semaphoreui/semaphore · error

error at templates[ ]

Error message

error at templates[%d]: %s

What it means

BackupFormat.Verify() validates each entry in backup.Schedules but wraps failures with a 'templates[%d]' prefix (the schedule's Verify validates its template reference). This error tells the caller the schedule at index i failed validation — most commonly because it references a template not present in templates[].

Solutions

  1. Read the wrapped inner message to identify the exact failure in schedules[i]
  2. Add the referenced template to templates[] in the backup file
  3. Fix schedules[i].template to match an existing templates[].name
  4. Remove the schedule entry if its workflow/template is intentionally excluded

Example fix

// before
{"templates": [{"name": "nightly-build"}], "schedules": [{"name": "cron", "template": "nightly-deploy"}]}
// after
{"templates": [{"name": "nightly-build"}, {"name": "nightly-deploy"}], "schedules": [{"name": "cron", "template": "nightly-deploy"}]}
Defensive patterns

Strategy: try-catch

Validate before calling

tplNames := map[string]bool{}
for _, t := range backup.Templates {
    tplNames[t.Name] = true
}
for i, s := range backup.Schedules {
    if !tplNames[s.Template] {
        return fmt.Errorf("schedules[%d].template %q not in templates[]", i, s.Template)
    }
}

Try / catch

if err := backup.Verify(); err != nil {
    if strings.HasPrefix(err.Error(), "error at templates[") && strings.Contains(err.Error(), "schedules") == false {
        // note: schedules failures are prefixed 'error at templates[%d]'
        return fmt.Errorf("invalid backup: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling BackupFormat.Verify() when schedules[i] fails its Verify — typically schedules[].template does not match any templates[].name in the backup, or the schedule name is duplicated.

Common situations: Schedules exported while referencing templates excluded from the backup; template renamed after the schedule was created; partial backups; merged backup files.

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


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

Appendix: source

Thrown at services/project/restore.go:548

	b.workflows = append(b.workflows, newWorkflow)
	return nil
}

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 {

View on GitHub (pinned to 1774ccb71a)