semaphoreui/semaphore · error

error at secret storage

Error message

error at secret storage[%d]: %s

What it means

This error wraps a per-item failure from BackupFormat.Verify() while validating backup.SecretStorages: the secret storage object at index i failed o.Verify(backup). A secret storage entry in the backup is invalid, so verification aborts and restore never starts.

Solutions

  1. Read the inner error after 'secret storage[i]:' for the exact validation failure
  2. Fix or remove the secret storage entry at that index in the backup
  3. Confirm the target Semaphore instance supports the secret storage type in the backup
  4. Re-export the backup from the source instance instead of editing manually
Defensive patterns

Strategy: validation

Validate before calling

for i, ss := range backup.SecretStorages {
    if ss == nil || ss.Name == "" || ss.Type == "" {
        return fmt.Errorf("secret storage[%d]: missing name/type before restore", i)
    }
}
if err := backup.Verify(); err != nil {
    return err
}

Type guard

func validSecretStorage(ss *SecretStorageBackup) bool { return ss != nil && ss.Name != "" && ss.Type != "" }

Try / catch

if err := backup.Verify(); err != nil {
    if strings.Contains(err.Error(), "secret storage[") {
        // fix the secret storage entry at the parsed index
    }
    return err
}

Prevention

When it happens

Trigger: Calling BackupFormat.Verify() where the secret storage at backup.SecretStorages[i] fails Verify — e.g. missing name/type, or shared/connection parameters referencing storages absent from the backup.

Common situations: Backups exported from an instance using a different secret backend (e.g. Vault vs internal) and restored elsewhere; schema changes between Semaphore versions; hand-edited backup files dropping referenced storages.

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/7be71daec37e8857. Report an issue: GitHub.

Appendix: source

Thrown at services/project/restore.go:568

	}
	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 {
		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 {

View on GitHub (pinned to 1774ccb71a)