glanceapp/glance · critical

decoding secret-key: %v

Error message

decoding secret-key: %v

What it means

Thrown during application startup when auth is configured (users exist) and the `auth.secret-key` value cannot be base64-decoded with standard encoding. The secret key is stored as base64 in the YAML config, so any character outside the standard base64 alphabet or wrong padding makes DecodeString fail.

Source

Thrown at internal/glance/glance.go:64

func newApplication(c *config) (*application, error) {
	app := &application{
		Version:    buildVersion,
		CreatedAt:  time.Now(),
		Config:     *c,
		slugToPage: make(map[string]*page),
		widgetByID: make(map[uint64]widget),
	}
	config := &app.Config

	//
	// Init auth
	//

	if len(config.Auth.Users) > 0 {
		secretBytes, err := base64.StdEncoding.DecodeString(config.Auth.SecretKey)
		if err != nil {
			return nil, fmt.Errorf("decoding secret-key: %v", err)
		}

		if len(secretBytes) != AUTH_SECRET_KEY_LENGTH {
			return nil, fmt.Errorf("secret-key must be exactly %d bytes", AUTH_SECRET_KEY_LENGTH)
		}

		app.usernameHashToUsername = make(map[string]string)
		app.failedAuthAttempts = make(map[string]*failedAuthAttempt)
		app.RequiresAuth = true

		for username := range config.Auth.Users {
			user := config.Auth.Users[username]
			usernameHash, err := computeUsernameHash(username, secretBytes)
			if err != nil {
				return nil, fmt.Errorf("computing username hash for user %s: %v", username, err)
			}
			app.usernameHashToUsername[string(usernameHash)] = username

View on GitHub (pinned to 91324e8de7)

Solutions

  1. Regenerate the key properly: `openssl rand -base64 64` and paste the single-line result into auth.secret-key
  2. Ensure no whitespace/newlines/url-safe substitutions are present; standard alphabet only (A-Z a-z 0-9 + / =)
  3. If the value comes from a template/env substitution, verify padding characters survive injection

Example fix

# before
auth:
  secret-key: "hGk9...raw-64-bytes...==("  # not valid base64
# after (generate correctly)
# openssl rand -base64 64
auth:
  secret-key: "K9dX...single-line-base64...=="
Defensive patterns

Strategy: validation

Validate before calling

// Validate secret-key before handing config to glance
import "encoding/base64"

func secretKeyValid(s string) error {
    b, err := base64.StdEncoding.DecodeString(s)
    if err != nil { return fmt.Errorf("secret-key is not standard base64: %w", err) }
    if len(b) != 64 { return fmt.Errorf("secret-key decodes to %d bytes, want 64", len(b)) }
    return nil
}

Try / catch

Treat as fatal config error; catch at startup, print the regen command (`openssl rand -base64 64`), and exit — never fall back to a default key.

Prevention

When it happens

Trigger: Setting `secret-key` to a raw 64-byte random string instead of its base64 encoding; hand-editing the key and introducing spaces, url-safe (-/_) characters, or truncating/wrapping the value; using base64url encoding instead of standard base64.

Common situations: Generating a key with `openssl rand 64` (raw bytes) instead of `openssl rand -base64 64`; copying a key with a line break from a terminal; secret injected via environment templating that mangles padding ('=' signs stripped).

Related errors


AI-assisted analysis of glanceapp/glance@91324e8de7 (2026-08-15). Data as JSON: /api/errors/fadd24063c185de0. Report an issue: GitHub.