passbolt/passbolt_api · error · BadRequestException

Please provide a valid email address.

Error message

Please provide a valid email address.

What it means

Thrown by UserRecoverService::assertUsername when the 'username' request field is missing, is not a string, or fails EmailValidationRule::check — i.e. it is not a syntactically valid email address. This is the first-line format check before the 'recover' validation rules are applied via a Users entity.

Solutions

  1. Include 'username' as a quoted string in the JSON body and ensure it is a valid email (local@domain.tld).
  2. Validate the email format client-side before calling the endpoint.
  3. Check your client code for undefined/empty variables being serialized.
  4. If the email is valid but still rejected, compare it against CakePHP's EmailValidationRule behavior (special characters, IDN) and try the canonical form.

Example fix

// before
curl -d '{"username":""}' /recover.json  // 400

// after
curl -d '{"username":"user@example.com"}' /recover.json
Defensive patterns

Strategy: validation

Validate before calling

const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (typeof username !== 'string' || !EMAIL_RE.test(username)) {
  throw new TypeError('username must be a valid email address');
}

Type guard

const isEmail = (v) => typeof v === 'string' && /^\S+@\S+\.\S+$/.test(v);

Try / catch

try {
  await recover({ username });
} catch (e) {
  if (e.response?.body?.message?.includes('valid email address')) {
    showFieldError('username', 'Enter a valid email address');
  }
}

Prevention

When it happens

Trigger: POST /recover.json with body missing 'username', with username as a non-string (null, number, object), or with a value that fails email syntax (e.g. "not-an-email", "a@b", "@x.com").

Common situations: Scripts interpolating an empty/undefined variable into the JSON body; internationalized or unusual-but-legal emails rejected by the strict rule; form field mis-mapping sending the name under a different key so username arrives null; automation that strips quotes making the email a non-string.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/c14c0befcc739e5d. Report an issue: GitHub.

Appendix: source

Thrown at src/Service/Users/UserRecoverService.php:157

        if (!in_array($case, self::ACCOUNT_RECOVERY_CASES)) {
            throw new BadRequestException(__('Account recovery reason not supported.'));
        }

        return $case;
    }

    /**
     * Assert some username data is provided
     *
     * @throws \Cake\Http\Exception\BadRequestException if the username is not valid
     * @throws \Cake\Http\Exception\BadRequestException if the username is not provided
     * @return string validated username
     */
    protected function assertUsername(): string
    {
        $username = $this->request->getData('username') ?? null;
        if (!isset($username) || !is_string($username) || !EmailValidationRule::check($username)) {
            throw new BadRequestException(__('Please provide a valid email address.'));
        }

        $user = $this->Users->newEntity([
            'username' => $username,
        ], [
            'validate' => 'recover',
            'accessibleFields' => [
                'username' => true,
            ],
        ]);

        if ($user->getErrors()) {
            throw new BadRequestException(__('Please provide a valid email address.'));
        }

        return $username;
    }

View on GitHub (pinned to 31c1bbc10f)