{"record":{"id":"26441a716607b8e4","repo":"knadh/listmonk","slug":"no-captcha-provider-enabled","errorCode":null,"errorMessage":"no captcha provider enabled","messagePattern":"no captcha provider enabled","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/captcha/captcha.go","lineNumber":142,"sourceCode":"\t\t\tSaltLength: 12,\n\t\t\tHMACKey:    c.altcha.HMACKey,\n\t\t\tExpires:    &exp,\n\t\t})\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"failed to create Altcha challenge: %w\", err)\n\t\t}\n\n\t\tchallengeJSON, err := json.Marshal(challenge)\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"failed to marshal Altcha challenge: %w\", err)\n\t\t}\n\n\t\treturn string(challengeJSON), nil\n\tcase ProviderHCaptcha:\n\t\t// hCaptcha generates challenges client-side.\n\t\treturn \"\", nil\n\tdefault:\n\t\treturn \"\", fmt.Errorf(\"no captcha provider enabled\")\n\t}\n}\n\n// Verify verifies a CAPTCHA response.\nfunc (c *Captcha) Verify(token string) (error, bool) {\n\tswitch c.provider {\n\tcase ProviderAltcha:\n\t\treturn c.verifyAltcha(token)\n\tcase ProviderHCaptcha:\n\t\treturn c.verifyHCaptcha(token)\n\tdefault:\n\t\treturn fmt.Errorf(\"no captcha provider enabled\"), false\n\t}\n}\n\n// verifyHCaptcha verifies an hCaptcha response.\nfunc (c *Captcha) verifyHCaptcha(token string) (error, bool) {\n\tresp, err := c.client.PostForm(hCaptchaURL, url.Values{","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/knadh/listmonk/blob/670c01717d48647093335cc23a6be6f4b79c3b6b/internal/captcha/captcha.go#L124-L160","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before: config\n[captcha]\n# provider not set\n// after\n[captcha]\nprovider = \"altcha\"\ncomplexity = 50000\nhmac_key = \"secret-hmac-key\"","handlingStrategy":"validation","validationCode":"switch cfg.Captcha.Provider {\ncase \"altcha\", \"hcaptcha\":\n  // ok\ndefault:\n  return fmt.Errorf(\"config: captcha.provider must be 'altcha' or 'hcaptcha', got %q\", cfg.Captcha.Provider)\n}","typeGuard":"func captchaProviderEnabled(provider string) bool {\n  p := strings.ToLower(provider)\n  return p == \"altcha\" || p == \"hcaptcha\"\n}","tryCatchPattern":"challenge, err := captcha.GenerateChallenge(ctx)\nif err != nil {\n  if err.Error() == \"no captcha provider enabled\" {\n    // config bug: fail loudly, do not silently render forms without captcha\n    log.Error(\"captcha not configured but form requires it\")\n    http.Error(w, \"captcha misconfigured\", http.StatusInternalServerError)\n    return\n  }\n}","preventionTips":["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"],"tags":["go","captcha","configuration","missing-config"],"backgroundTag":"missing-config-value","analyzedSha":"670c01717d48647093335cc23a6be6f4b79c3b6b","analyzedAt":"2026-09-01T03:39:35.452Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}