glanceapp/glance · critical

secret-key must be exactly %d bytes

Error message

secret-key must be exactly %d bytes

What it means

Startup fails when the base64-decoded auth secret key is not exactly AUTH_SECRET_KEY_LENGTH bytes (32-byte token secret + 32-byte username-hash secret = 64 bytes). The key is split into two HMAC-SHA256 secrets at runtime, so a wrong length would panic on slicing; the check turns that into a clear error.

Source

Thrown at internal/glance/glance.go:68

		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

			if user.PasswordHashString != "" {
				user.PasswordHash = []byte(user.PasswordHashString)
				user.PasswordHashString = ""
			} else {

View on GitHub (pinned to 91324e8de7)

Solutions

  1. Regenerate with the documented command that yields exactly 64 bytes: `openssl rand -base64 64`
  2. Verify: `echo -n '<key>' | base64 -d | wc -c` must print 64
  3. Do not trim, shorten, or append characters to the key

Example fix

# verify length
# echo -n "$SECRET_KEY" | base64 -d | wc -c
64
# if not 64, regenerate:
# openssl rand -base64 64
Defensive patterns

Strategy: validation

Validate before calling

b, err := base64.StdEncoding.DecodeString(cfg.Auth.SecretKey)
if err == nil && len(b) != 64 {
    return fmt.Errorf("secret-key length %d != 64; regenerate with: openssl rand -base64 64", len(b))
}

Try / catch

Fail fast at startup with the regenerate command in the error message; no retry is meaningful for a static secret.

Prevention

When it happens

Trigger: Decoding succeeds but the plaintext is 63, 65, or any non-64 byte count: e.g. `openssl rand -base64 63`, trimming characters off the key, or decoding a key generated for a different glance version with a different length requirement.

Common situations: Using `head -c 63` style shell truncation; regenerating a key after upgrading glance when the length requirement changed; guessing the length instead of copying the documented command.

Related errors


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