semaphoreui/semaphore · error
read jwt signing key option
Error message
read jwt signing key option: %w
What it means
Returned by CheckJWTSigningKey in util/jwt.go when the read-only inspection used by 'vault check' cannot load the jwt_signing_key option from the OptionStore. It is a thin wrapping guard around store.GetOption: the %w carries the underlying database error, and none of the key classification (none/active/rekey-pending/legacy/missing) could be performed because the stored value itself was unreadable.
Solutions
- Check the wrapped error for the DB-level cause (connection, permissions, missing table)
- Ensure migrations have created the options table before running vault check
- Retry the check once the database is reachable
- Confirm the DB credentials used by the CLI have read access to the options table
Defensive patterns
Strategy: retry
When it happens
Trigger: Thrown at util/jwt.go:110 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of semaphoreui/semaphore@1774ccb71a (2026-09-07).
Data as JSON: /api/errors/5d30f5a4f48e6452.
Report an issue: GitHub.
Appendix: source
Thrown at util/jwt.go:110
encrypted, err := encryptJWTKey(pemBytes)
if err != nil {
return nil, err
}
if err := store.SetOption(jwtSigningKeyOption, encrypted); err != nil {
return nil, fmt.Errorf("persist signing key: %w", err)
}
return pemBytes, nil
}
// CheckJWTSigningKey classifies the stored JWT signing key for `vault check`:
// "" (none), "active:<id>", "rekey pending:<id>", "legacy (no id)", or
// "MISSING KEY <id>". Read-only.
func CheckJWTSigningKey(store OptionStore) (slot string, err error) {
stored, err := store.GetOption(jwtSigningKeyOption)
if err != nil {
return "", fmt.Errorf("read jwt signing key option: %w", err)
}
if stored == "" {
return "", nil
}
return Config.classifyOptionSecret(stored), nil
}
// RekeyJWTSigningKey re-encrypts the stored JWT signing key under the active
// option key (stamping its id). It decrypts via the option keyset, the access
// fallback, and — when supplied — oldKey (the legacy `vault rekey --old-key`
// flow). No-op when no key is stored or the ciphertext is unchanged.
func RekeyJWTSigningKey(store OptionStore, oldKey string) error {
stored, err := store.GetOption(jwtSigningKeyOption)
if err != nil {
return fmt.Errorf("read jwt signing key option: %w", err)
}
if stored == "" {
return nilView on GitHub (pinned to 1774ccb71a)