{"record":{"id":"72e23ee1f51177e5","repo":"Billionmail/BillionMail","slug":"validation-code-id-and-code-cannot-be-empty","errorCode":null,"errorMessage":"Validation code ID and code cannot be empty","messagePattern":"Validation code ID and code cannot be empty","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"core/internal/controller/rbac/rbac_v1_auth.go","lineNumber":69,"sourceCode":"\n\tif loginRetries >= maxRetries {\n\t\tk := \"USER_LOGIN_RETRIES_RELEASE_TIME:\" + clientIp\n\t\treleaseTime, blocked := public.GetCache(k).(int64)\n\t\tif !blocked {\n\t\t\treleaseTime = time.Now().Unix() + int64(blockTime)\n\t\t\tpublic.SetCache(k, releaseTime, blockTime)\n\t\t}\n\n\t\terr = fmt.Errorf(\"Login failed too many times, please try again after %d seconds\", releaseTime-time.Now().Unix())\n\t\treturn\n\t}\n\n\t// Check if validation code is required\n\tif mustValidateCode {\n\t\tvalidateSuccess = false\n\n\t\tif req.ValidateCodeId == \"\" || req.ValidateCode == \"\" {\n\t\t\terr = fmt.Errorf(\"Validation code ID and code cannot be empty\")\n\t\t\treturn\n\t\t}\n\n\t\tif !service.VerifyCaptcha(req.ValidateCodeId, req.ValidateCode) {\n\t\t\terr = fmt.Errorf(\"Invalid validation code\")\n\t\t\treturn\n\t\t}\n\n\t\tvalidateSuccess = true\n\t}\n\n\t// Verify username and password\n\taccount, err := service.Account().Login(ctx, req.Username, req.Password)\n\tif err != nil {\n\t\terr = fmt.Errorf(\"Invalid username or password\")\n\t\treturn\n\t}\n","sourceCodeStart":51,"sourceCodeEnd":87,"githubUrl":"https://github.com/Billionmail/BillionMail/blob/fc36c76c050c3775c5e899faf7403cf0262d2744/core/internal/controller/rbac/rbac_v1_auth.go#L51-L87","documentation":"When the login flow determines a captcha/validation code is required (mustValidateCode), the request must carry both ValidateCodeId and ValidateCode. If either is empty the handler rejects the request before even attempting verification.","triggerScenarios":"Submitting a login that requires captcha without the captcha fields (client didn't render/fetch the captcha); frontend not updated for the captcha-enforced flow; captcha component failing to load so fields stay empty; API clients calling login directly without captcha support.","commonSituations":"Login attempts from headless scripts after the server started requiring captcha; a UI bug hiding the captcha input; stale frontend bundle predating the captcha requirement; users clicking login before captcha finishes loading.","solutions":["First fetch a captcha challenge (obtaining ValidateCodeId) and render it to the user","Send both validate_code_id and validate_code in the login request","Update/refresh the frontend client so it supports the captcha flow","Check that the captcha service is up if the widget silently fails to initialize"],"exampleFix":"// before\nawait api.login({ username, password })\n// after\nconst captcha = await api.getCaptcha();\nawait api.login({ username, password, validate_code_id: captcha.id, validate_code: userInput })","handlingStrategy":"validation","validationCode":"if (!validateCodeId || !validateCode) {\n  throw new Error('obtain a captcha first: both id and code are required');\n}","typeGuard":"function hasCaptcha(r: { validate_code_id?: string; validate_code?: string }): r is { validate_code_id: string; validate_code: string } {\n  return typeof r.validate_code_id === 'string' && r.validate_code_id !== '' && typeof r.validate_code === 'string' && r.validate_code !== '';\n}","tryCatchPattern":"try {\n  await api.login(body);\n} catch (err) {\n  if (String(err.message).includes('Validation code ID and code cannot be empty')) {\n    const captcha = await api.getCaptcha(); // then re-render and retry\n  }\n}","preventionTips":["Always fetch a captcha challenge before login when the server requires it","Keep the frontend in sync with captcha-enforcement changes","Disable the submit button until captcha is loaded and filled"],"tags":["validation","captcha","authentication"],"backgroundTag":"missing-required-argument","analyzedSha":"fc36c76c050c3775c5e899faf7403cf0262d2744","analyzedAt":"2026-09-05T21:28:54.019Z","contentChangedAt":"2026-09-05T21:28:54.019Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}