semaphoreui/semaphore · error

error at runners[ ]

Error message

error at runners[%d]: %s

What it means

This error wraps a per-item failure from BackupFormat.Verify() while validating backup.Runners: the runner at index i failed o.Verify(backup). A runner entry in the backup is invalid (missing fields, bad token config, or broken references), so restore is blocked at the validation stage.

Solutions

  1. Read the inner error after 'runners[i]:' for the exact validation failure
  2. Fix or remove the runner entry at the reported index in the backup file
  3. Ensure referenced entities (project/secret storage) exist elsewhere in the backup
  4. Re-export the backup from the source instance to regenerate a consistent runners section
Defensive patterns

Strategy: validation

Validate before calling

for i, r := range backup.Runners {
    if r == nil || r.Name == "" {
        return fmt.Errorf("runners[%d]: missing name before restore", i)
    }
}
if err := backup.Verify(); err != nil {
    return err
}

Type guard

func validRunner(r *RunnerBackup) bool { return r != nil && r.Name != "" }

Try / catch

if err := backup.Verify(); err != nil {
    if strings.Contains(err.Error(), "runners[") {
        // inspect the runner entry at the reported index
    }
    return err
}

Prevention

When it happens

Trigger: Calling BackupFormat.Verify() where the runner at backup.Runners[i] fails Verify — e.g. empty runner name, missing token/project reference, or an endpoint that doesn't match the runner type.

Common situations: Backups exported between Semaphore versions with changed runner schema; runners referencing project entities removed from the backup; hand-edited or 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/7b9d7dae265698c9. Report an issue: GitHub.

Appendix: source

Thrown at services/project/restore.go:583

	}
	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 {
		if err := o.Verify(backup); err != nil {
			return fmt.Errorf("error at templates[%d]: %s", i, err.Error())
		}
	}
	for i, o := range backup.Roles {
		if err := o.Verify(backup); err != nil {
			return fmt.Errorf("error at roles[%d]: %s", i, err.Error())
		}
	}
	for i, o := range backup.Runners {
		if err := o.Verify(backup); err != nil {
			return fmt.Errorf("error at runners[%d]: %s", i, err.Error())
		}
	}
	for i, o := range backup.Workflows {
		if err := o.Verify(backup); err != nil {
			return fmt.Errorf("error at workflows[%d]: %s", i, err.Error())
		}
	}

	return nil
}

func (backup *BackupFormat) Restore(user db.User, store db.Store, workflowStore db.WorkflowManager) (*db.Project, error) {
	var b = BackupDB{store: store, workflowStore: workflowStore}
	project := backup.Meta.Project

	// Prevent importing a project with a name that already exists
	existingProjects, err := b.store.GetAllProjects()
	if err == nil {

View on GitHub (pinned to 1774ccb71a)