knadh/listmonk · error
no captcha provider enabled
Error message
no captcha provider enabled
What it means
GenerateChallenge returns this when the Captcha instance's provider field is neither ProviderAltcha nor ProviderHCaptcha — i.e. no CAPTCHA provider was configured/enabled. The switch has no matching case, so the default branch errors out. Any caller requesting a challenge from an unconfigured Captcha gets this immediately.
Source
Thrown at internal/captcha/captcha.go:142
SaltLength: 12,
HMACKey: c.altcha.HMACKey,
Expires: &exp,
})
if err != nil {
return "", fmt.Errorf("failed to create Altcha challenge: %w", err)
}
challengeJSON, err := json.Marshal(challenge)
if err != nil {
return "", fmt.Errorf("failed to marshal Altcha challenge: %w", err)
}
return string(challengeJSON), nil
case ProviderHCaptcha:
// hCaptcha generates challenges client-side.
return "", nil
default:
return "", fmt.Errorf("no captcha provider enabled")
}
}
// Verify verifies a CAPTCHA response.
func (c *Captcha) Verify(token string) (error, bool) {
switch c.provider {
case ProviderAltcha:
return c.verifyAltcha(token)
case ProviderHCaptcha:
return c.verifyHCaptcha(token)
default:
return fmt.Errorf("no captcha provider enabled"), false
}
}
// verifyHCaptcha verifies an hCaptcha response.
func (c *Captcha) verifyHCaptcha(token string) (error, bool) {
resp, err := c.client.PostForm(hCaptchaURL, url.Values{View on GitHub (pinned to 670c01717d)
Solutions
- Set a valid provider in config (altcha or hcaptcha) and confirm the value matches the expected constant casing.
- Guard call sites: only call GenerateChallenge when captcha is enabled in the current environment.
- Add a startup validation that errors if forms require captcha but no provider is configured.
- Normalize the provider string in the constructor (strings.ToLower) before storing it.
Example fix
// before: config [captcha] # provider not set // after [captcha] provider = "altcha" complexity = 50000 hmac_key = "secret-hmac-key"
Defensive patterns
Strategy: validation
Validate before calling
switch cfg.Captcha.Provider {
case "altcha", "hcaptcha":
// ok
default:
return fmt.Errorf("config: captcha.provider must be 'altcha' or 'hcaptcha', got %q", cfg.Captcha.Provider)
} Type guard
func captchaProviderEnabled(provider string) bool {
p := strings.ToLower(provider)
return p == "altcha" || p == "hcaptcha"
} Try / catch
challenge, err := captcha.GenerateChallenge(ctx)
if err != nil {
if err.Error() == "no captcha provider enabled" {
// config bug: fail loudly, do not silently render forms without captcha
log.Error("captcha not configured but form requires it")
http.Error(w, "captcha misconfigured", http.StatusInternalServerError)
return
}
} Prevention
- Set captcha.provider explicitly in every environment's config
- Validate the full captcha config block at application startup
- Compare provider strings case-insensitively (or normalize them in the constructor)
- Document that disabling captcha also requires disabling captcha-protected forms
When it happens
Trigger: Calling GenerateChallenge on a Captcha built with an empty/unknown provider string, or a New constructor that skipped provider configuration because the captcha config section was absent or misspelled (e.g. provider="Altcha" vs "altcha" casing mismatch).
Common situations: Config file lacks the [captcha] section or provider key; provider value typo or wrong casing; captcha intentionally disabled in some environments but code paths still call GenerateChallenge unconditionally.
Understand the failure class
Background: "missing required config value" errors: why libraries refuse to start when a configuration key is empty, unset, or blank — this error's family across 48 libraries.
Related errors
- failed to create Altcha challenge: %w
- webhook key is not configured
- failed to marshal Altcha challenge: %w
- hCaptcha failed: %s
- failed to verify captcha solution: %w
AI-assisted analysis of knadh/listmonk@670c01717d (2026-09-01).
Data as JSON: /api/errors/26441a716607b8e4.
Report an issue: GitHub.