semaphoreui/semaphore · error

err

Error message

err

What it means

In `vault rekey --rollback <file>`, the panic fires when `rollbackAccessKeys` fails. Rollback opens the backup file, parses each JSON line, decrypts the current secret to populate validation fields, and writes the backed-up ciphertext back via `store.UpdateAccessKey`. Any of open/parse/decrypt/update failures abort with a panic.

Solutions

  1. Verify the --rollback path exists and is the complete backup file produced by --backup.
  2. Fix the keyset so the current (rekeyed) ciphertexts can be decrypted — rollback must decrypt them before writing back old values.
  3. Inspect the wrapped error: json unmarshal errors point at a specific corrupt line; DB errors point at store issues.
  4. If rollback is impossible, re-run rekey with the correct keys instead of rolling back.

Example fix

// before
if err := rollbackAccessKeys(store, encryptionService, targetVaultArgs.rollbackFile); err != nil {
    panic(err)
}
// after
if err := rollbackAccessKeys(store, encryptionService, targetVaultArgs.rollbackFile); err != nil {
    fmt.Fprintf(os.Stderr, "rollback failed: %v\n", err)
    os.Exit(1)
}
Defensive patterns

Strategy: validation

Validate before calling

if fi, err := os.Stat(rollbackFile); err != nil || fi.IsDir() {
    fmt.Fprintf(os.Stderr, "rollback file %s not readable\n", rollbackFile)
    os.Exit(1)
}

Try / catch

if err := rollbackAccessKeys(store, svc, path); err != nil {
    fmt.Fprintf(os.Stderr, "rollback failed: %v\n", err)
    os.Exit(1)
}

Prevention

When it happens

Trigger: Running `semaphore vault rekey --rollback backup.jsonl` when the backup file does not exist or is unreadable, a line is not valid JSON, a stored key cannot be decrypted with the current keyset, or the UPDATE fails in the database.

Common situations: Path typo or backup written to another host; partially truncated/corrupted backup file; keyset changed after rekey so current ciphertext cannot be deserialized; DB write permission issues.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


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

Appendix: source

Thrown at cli/cmd/vault_rekey.go:54

	Long: "Re-encrypt all locally stored secrets (access keys and the JWT signing key)\n" +
		"under the active key, stamping its key id into each value.\n\n" +
		"Zero-downtime rotation:\n" +
		"  1. Add a new key to the keyset (a file in keys_folder, or a keys: entry) and\n" +
		"     point active.access_key (or access_key_file) at it; reload applies it\n" +
		"     within keys_poll_interval, or send `kill -HUP <pid>`.\n" +
		"  2. Run `vault rekey` to re-encrypt existing data to the new key.\n" +
		"  3. Run `vault check`; once the old key shows 0 rows it is safe to remove.\n\n" +
		"Legacy: `vault rekey --old-key <old-key>` decrypts un-prefixed data with an\n" +
		"explicit old key.",
	Run: func(cmd *cobra.Command, args []string) {
		store := createStore("")
		defer store.Close()

		encryptionService := server.NewAccessKeyEncryptionService(store, store, store, store)

		if targetVaultArgs.rollbackFile != "" {
			if err := rollbackAccessKeys(store, encryptionService, targetVaultArgs.rollbackFile); err != nil {
				panic(err)
			}
			fmt.Println("Rollback complete.")
			return
		}

		if targetVaultArgs.backupFile != "" {
			if err := backupAccessKeys(store, targetVaultArgs.backupFile); err != nil {
				panic(err)
			}
			fmt.Printf("Backup written to %s\n", targetVaultArgs.backupFile)
		}

		if err := encryptionService.RekeyAccessKeys(targetVaultArgs.oldKey); err != nil {
			panic(err)
		}

		if err := util.RekeyJWTSigningKey(store, targetVaultArgs.oldKey); err != nil {
			panic(err)

View on GitHub (pinned to 1774ccb71a)