flipped-aurora/gin-vue-admin · error

GVA_CACHE 未初始化

Error message

GVA_CACHE 未初始化

What it means

CacheStore.Set writes a captcha answer into the global GVA_CACHE with the store's key prefix and expiration. If the global cache singleton was never initialized (global.GVA_CACHE == nil), it refuses to write and returns this error; the caller (captcha Generate) is expected to degrade gracefully rather than panic.

Source

Thrown at server/utils/captcha/cache_store.go:30

const defaultCaptchaExpiration = time.Second * 180

type CacheStore struct {
	Expiration time.Duration
	PreKey     string
}

// NewCacheStore 返回一个基于 GVA_CACHE 的验证码存储,前缀隔离避免与其它缓存键冲突。
func NewCacheStore() *CacheStore {
	return &CacheStore{
		Expiration: defaultCaptchaExpiration,
		PreKey:     "CAPTCHA_",
	}
}

// Set 写入验证码答案,按 Expiration 过期。GVA_CACHE 未就绪时返回错误,由上层(Generate)优雅处理。
func (cs *CacheStore) Set(id string, value string) error {
	if global.GVA_CACHE == nil {
		return errors.New("GVA_CACHE 未初始化")
	}
	global.GVA_CACHE.Set(cs.PreKey+id, value, cs.Expiration)
	return nil
}

// Get 读取验证码答案,clear=true 时读取后删除。未命中或类型不符返回空串。
func (cs *CacheStore) Get(id string, clear bool) string {
	if global.GVA_CACHE == nil {
		return ""
	}
	key := cs.PreKey + id
	v, ok := global.GVA_CACHE.Get(key)
	if !ok {
		return ""
	}
	if clear {
		global.GVA_CACHE.Delete(key)
	}

View on GitHub (pinned to 3136500ef3)

Solutions

  1. Initialize the cache at startup so global.GVA_CACHE is non-nil (server/initialize path), then retry the captcha operation.
  2. In tests, use testutil.InitMemoryCache(t, 0) from server/internal/testutil before calling captcha code.
  3. If the environment intentionally has no cache, treat the error upstream: Generate handles it gracefully; avoid calling Set directly and surface a 'captcha unavailable' response.

Example fix

// before
cs := &utils.CacheStore{...}
err := cs.Set(id, val) // panic-free but errors: GVA_CACHE 未初始化
// after
func TestCaptcha(t *testing.T) {
    testutil.InitMemoryCache(t, 0)
    err := cs.Set(id, val) // GVA_CACHE now set
}
Defensive patterns

Strategy: try-catch

Validate before calling

if global.GVA_CACHE == nil {
    // cache not ready; skip captcha or init first
    testutil.InitMemoryCache(t, 0) // in tests
}

Type guard

func cacheReady() bool { return global.GVA_CACHE != nil }

Try / catch

if err := cs.Set(id, value); err != nil {
    // degrade gracefully: captcha generation unavailable
    log.Warn("captcha disabled: %v", err)
    return captchaImage{}, nil // caller treats as no-captcha mode
}

Prevention

When it happens

Trigger: Calling captcha Generate/Set before cache initialization has run, or in contexts where server/initialize never assigned global.GVA_CACHE (e.g. minimal test harness, tool binaries, or a config that skips cache init).

Common situations: Unit tests that exercise captcha code without testutil.InitMemoryCache; CLI/migration binaries that import utils but never run initialize; deployment configs where cache init failed silently at startup.

Related errors


AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31). Data as JSON: /api/errors/61348fe4e05fa5cc. Report an issue: GitHub.