semaphoreui/semaphore · error
read option
Error message
read option: %w
What it means
Returned by loadOrCreateJWTKey in util/jwt.go when the underlying OptionStore fails to read the jwt_signing_key option row from the database. It is a thin wrapping guard around store.GetOption: the %w carries the actual database error (connection failure, missing table, query error), and only the read step is affected — key decryption or generation happens in later branches.
Solutions
- Check the wrapped error for the concrete DB failure (connection refused, table missing, timeout)
- Verify database connectivity and that migrations ran so the options table exists
- Retry service startup after the database is reachable — a transient outage at boot is a common cause
- Ensure the service's DB user has SELECT permission on the options table
Defensive patterns
Strategy: retry
When it happens
Trigger: Thrown at util/jwt.go:79 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/6268223df07409e8.
Report an issue: GitHub.
Appendix: source
Thrown at util/jwt.go:79
fmt.Fprintf(os.Stderr, "jwt: invalid jwt_max_ttl %q, falling back to 24h: %v\n", Config.JWT.MaxTTL, err)
}
}
return jwt.SignerOptions{
Issuer: Config.JWT.Issuer,
DefaultTTL: ttl,
MaxTTL: maxTTL,
}
}
// loadOrCreateJWTKey returns the raw PEM bytes of the JWT signing key. It
// reads the encrypted value from the database, decrypts it, and returns the
// plaintext PEM. If no key exists yet it generates one, persists it, and
// returns the plaintext PEM.
func loadOrCreateJWTKey(store OptionStore) ([]byte, error) {
stored, err := store.GetOption(jwtSigningKeyOption)
if err != nil {
return nil, fmt.Errorf("read option: %w", err)
}
if stored != "" {
return decryptJWTKey(stored)
}
// No key in DB yet
pemBytes, err := jwt.GenerateKeyPEM()
if err != nil {
return nil, err
}
encrypted, err := encryptJWTKey(pemBytes)
if err != nil {
return nil, err
}
if err := store.SetOption(jwtSigningKeyOption, encrypted); err != nil {View on GitHub (pinned to 1774ccb71a)