Billionmail/BillionMail · warning

Validation code ID and code cannot be empty

Error message

Validation code ID and code cannot be empty

What it means

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.

Source

Thrown at core/internal/controller/rbac/rbac_v1_auth.go:69

	if loginRetries >= maxRetries {
		k := "USER_LOGIN_RETRIES_RELEASE_TIME:" + clientIp
		releaseTime, blocked := public.GetCache(k).(int64)
		if !blocked {
			releaseTime = time.Now().Unix() + int64(blockTime)
			public.SetCache(k, releaseTime, blockTime)
		}

		err = fmt.Errorf("Login failed too many times, please try again after %d seconds", releaseTime-time.Now().Unix())
		return
	}

	// Check if validation code is required
	if mustValidateCode {
		validateSuccess = false

		if req.ValidateCodeId == "" || req.ValidateCode == "" {
			err = fmt.Errorf("Validation code ID and code cannot be empty")
			return
		}

		if !service.VerifyCaptcha(req.ValidateCodeId, req.ValidateCode) {
			err = fmt.Errorf("Invalid validation code")
			return
		}

		validateSuccess = true
	}

	// Verify username and password
	account, err := service.Account().Login(ctx, req.Username, req.Password)
	if err != nil {
		err = fmt.Errorf("Invalid username or password")
		return
	}

View on GitHub (pinned to fc36c76c05)

Solutions

  1. First fetch a captcha challenge (obtaining ValidateCodeId) and render it to the user
  2. Send both validate_code_id and validate_code in the login request
  3. Update/refresh the frontend client so it supports the captcha flow
  4. Check that the captcha service is up if the widget silently fails to initialize

Example fix

// before
await api.login({ username, password })
// after
const captcha = await api.getCaptcha();
await api.login({ username, password, validate_code_id: captcha.id, validate_code: userInput })
Defensive patterns

Strategy: validation

Validate before calling

if (!validateCodeId || !validateCode) {
  throw new Error('obtain a captcha first: both id and code are required');
}

Type guard

function hasCaptcha(r: { validate_code_id?: string; validate_code?: string }): r is { validate_code_id: string; validate_code: string } {
  return typeof r.validate_code_id === 'string' && r.validate_code_id !== '' && typeof r.validate_code === 'string' && r.validate_code !== '';
}

Try / catch

try {
  await api.login(body);
} catch (err) {
  if (String(err.message).includes('Validation code ID and code cannot be empty')) {
    const captcha = await api.getCaptcha(); // then re-render and retry
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of Billionmail/BillionMail@fc36c76c05 (2026-09-05). Data as JSON: /api/errors/72e23ee1f51177e5. Report an issue: GitHub.