apache/answer · warning

captcha not exist

Error message

captcha not exist

What it means

Returned by GetCaptcha when the cache holds no value for the given key: Cache.GetString reports exist=false and the repo converts that into this error. Captcha values are stored with a TTL, so a missing entry usually means the captcha expired or the key was deleted/never set.

Source

Thrown at internal/repo/captcha/captcha.go:106

}

// SetCaptcha set captcha to cache
func (cr *captchaRepo) SetCaptcha(ctx context.Context, key, captcha string) (err error) {
	err = cr.data.Cache.SetString(ctx, key, captcha, 6*time.Minute)
	if err != nil {
		err = errors.InternalServer(reason.DatabaseError).WithError(err).WithStack()
	}
	return
}

// GetCaptcha get captcha from cache
func (cr *captchaRepo) GetCaptcha(ctx context.Context, key string) (captcha string, err error) {
	captcha, exist, err := cr.data.Cache.GetString(ctx, key)
	if err != nil {
		return "", err
	}
	if !exist {
		return "", fmt.Errorf("captcha not exist")
	}
	return captcha, nil
}

func (cr *captchaRepo) DelCaptcha(ctx context.Context, key string) (err error) {
	err = cr.data.Cache.Del(ctx, key)
	if err != nil {
		log.Debug(err)
	}
	return nil
}

View on GitHub (pinned to 3b9f137061)

Solutions

  1. Return a 'captcha expired, please refresh' response to the user instead of a 500, and issue a new captcha.
  2. Increase the captcha TTL in cache configuration if it expires too quickly for real users.
  3. Verify all app instances share the same Redis/cache backend.
  4. Deliver the same cache key used at SetCaptcha time (no key mangling/prefix mismatch).

Example fix

// before
captcha, exist, err := cr.data.Cache.GetString(ctx, key)
if !exist {
    return "", fmt.Errorf("captcha not exist")
}
// after
captcha, exist, err := cr.data.Cache.GetString(ctx, key)
if err != nil {
    return "", err
}
if !exist {
    return "", ErrCaptchaExpired // caller maps to 4xx 'captcha expired, refresh'
}
Defensive patterns

Strategy: try-catch

Validate before calling

// before submit: ensure a captcha was issued and is recent
if captchaKey == "" || time.Since(captchaIssuedAt) > captchaTTL {
    // fetch a fresh captcha instead of verifying a stale one
    return errors.New("captcha missing or likely expired, request a new one")
}

Type guard

func captchaUsable(key string, issuedAt time.Time, ttl time.Duration) bool {
    return key != "" && time.Since(issuedAt) < ttl
}

Try / catch

answer, err := captchaRepo.GetCaptcha(ctx, key)
if err != nil {
    if strings.Contains(err.Error(), "captcha not exist") {
        return http.StatusBadRequest, "captcha expired, please refresh"
    }
    return http.StatusInternalServerError, err.Error()
}

Prevention

When it happens

Trigger: Looking up a captcha by a key that was never Set, a key already consumed by DelCaptcha after verification, or one that expired from the cache.

Common situations: User takes longer than the captcha TTL to submit the form; user double-submits (first verify deletes the key); Redis restarted/flushed between issuance and verification; load-balanced deployments pointing at different cache instances.

Related errors


AI-assisted analysis of apache/answer@3b9f137061 (2026-09-05). Data as JSON: /api/errors/d90c85c851c56178. Report an issue: GitHub.