{"record":{"id":"20b757082ff9cc5a","repo":"knadh/listmonk","slug":"failed-to-create-altcha-challenge-w","errorCode":null,"errorMessage":"failed to create Altcha challenge: %w","messagePattern":"failed to create Altcha challenge: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/captcha/captcha.go","lineNumber":129,"sourceCode":"\treturn c.provider\n}\n\n// GenerateChallenge generates a challenge for the active provider.\n// For hCaptcha, this returns empty string as challenges are generated client-side.\n// For Altcha, this returns a JSON challenge.\nfunc (c *Captcha) GenerateChallenge() (string, error) {\n\tswitch c.provider {\n\tcase ProviderAltcha:\n\t\texp := time.Now().Add(5 * time.Minute)\n\t\tchallenge, err := altcha.CreateChallenge(altcha.ChallengeOptions{\n\t\t\tAlgorithm:  altcha.SHA256,\n\t\t\tMaxNumber:  int64(c.altcha.Complexity),\n\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) {","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/knadh/listmonk/blob/670c01717d48647093335cc23a6be6f4b79c3b6b/internal/captcha/captcha.go#L111-L147","documentation":"GenerateChallenge wraps an error from the altcha library's Challenge call when creating a proof-of-work challenge for the Altcha CAPTCHA provider. Common inner causes are invalid configuration (bad HMAC key, non-positive complexity, bad expiry) or internal altcha failures. The challenge is the first step of the Altcha verify flow, so this error blocks form rendering.","triggerScenarios":"Calling GenerateChallenge with c.provider == ProviderAltcha when altcha.Challenge fails — e.g. HMACKey is empty/invalid, Complexity is zero or negative, the Expires time is in the past, or the altcha dependency returns an unexpected error.","commonSituations":"Forgot to configure altcha.HMACKey in config; Complexity left at 0 after a config refactor; HMAC key mismatch later causing verification issues traced back here; upgrading the altcha library to a version with different Challenge options.","solutions":["Check the captcha/altcha configuration: ensure HMACKey is a non-empty secure secret and Complexity is a positive integer.","Confirm the Expires timestamp passed to altcha.Challenge is in the future.","Unwrap the error (%w) to see altcha's inner message and fix accordingly.","Pin/verify the altcha library version matches the option fields used (MaxNumber, SaltLength, HMACKey, Expires)."],"exampleFix":"// before: zero-value config silently passed to altcha\n// config: [captcha] provider=\"altcha\" complexity=0 hmac_key=\"\"\n// after: fail fast at startup\nif c.provider == ProviderAltcha && (c.altcha.HMACKey == \"\" || c.altcha.Complexity <= 0) {\n  return errors.New(\"altcha provider requires non-empty HMACKey and positive Complexity\")\n}","handlingStrategy":"validation","validationCode":"if c.provider == \"altcha\" {\n  if c.altcha.HMACKey == \"\" {\n    return errors.New(\"altcha hmac_key is required\")\n  }\n  if c.altcha.Complexity <= 0 {\n    return errors.New(\"altcha complexity must be positive\")\n  }\n}","typeGuard":"func altchaConfigValid(cfg AltchaConfig) bool {\n  return cfg.HMACKey != \"\" && cfg.Complexity > 0\n}","tryCatchPattern":"challenge, err := captcha.GenerateChallenge(r.Context())\nif err != nil {\n  if strings.Contains(err.Error(), \"failed to create Altcha challenge\") {\n    log.Error(\"altcha challenge generation failed\", \"err\", err)\n    http.Error(w, \"captcha unavailable\", http.StatusServiceUnavailable)\n    return\n  }\n  http.Error(w, \"internal error\", http.StatusInternalServerError)\n}","preventionTips":["Validate HMACKey and Complexity at startup, not at first request","Generate the HMAC key once and store it in a secret manager","Pin the altcha library version and review its Challenge option struct on upgrades","Add a health check that generates a throwaway challenge periodically"],"tags":["go","captcha","altcha","proof-of-work","configuration"],"backgroundTag":"challenge-generation-failed","analyzedSha":"670c01717d48647093335cc23a6be6f4b79c3b6b","analyzedAt":"2026-09-01T03:39:35.452Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}