passbolt/passbolt_api · error · Cake\Http\Exception\InternalErrorException

Invalid UserControl username.

Error message

Invalid UserControl username.

What it means

UserAccessControl::__construct() validates its optional $username argument with EmailValidationRule::check(). If a username is supplied that is not a valid email address, it throws InternalErrorException('Invalid UserControl username.'), because the UAC username is always expected to be the user's email.

Solutions

  1. Validate the email before constructing the object (EmailValidationRule::check) and return a client error for bad input.
  2. Pass null instead of an empty string when the username is unknown — only set it when it is a valid email.
  3. Ensure the value passed is the user's email address, not a display name or login handle.

Example fix

// before
$uac = new UserAccessControl($role, $userId, $postData['username']); // 500 if not email
// after
$username = $postData['username'] ?? null;
if ($username !== null && !EmailValidationRule::check($username)) {
    throw new BadRequestException('Invalid username.');
}
$uac = new UserAccessControl($role, $userId, $username);
Defensive patterns

Strategy: validation

Validate before calling

if ($username !== null && !EmailValidationRule::check($username)) {
    throw new BadRequestException('A valid email address is required.');
}
$uac = new UserAccessControl($roleName, $userId, $username);

Type guard

function isValidUsername(?string $username): bool {
    return $username === null || EmailValidationRule::check($username);
}

Try / catch

try {
    $uac = new UserAccessControl($roleName, $userId, $username);
} catch (\Cake\Http\Exception\InternalErrorException $e) {
    if (str_contains($e->getMessage(), 'Invalid UserControl username')) {
        throw new BadRequestException('Invalid username supplied.');
    }
    throw $e;
}

Prevention

When it happens

Trigger: Constructing `new UserAccessControl($roleName, $userId, $username)` where $username fails email validation — e.g. passing a username/login string that is not an email, an empty-string instead of null, or user-supplied input without validation.

Common situations: Passing request data (username field) directly into UserAccessControl; tests using placeholder names like 'ada' or 'test'; legacy accounts with malformed emails in the database being passed through.

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/bc57dc98cbe7cd5e. Report an issue: GitHub.

Appendix: source

Thrown at src/Utility/UserAccessControl.php:63

    /**
     * @var string|null
     */
    private ?string $username = null;

    /**
     * UserAccessControl constructor.
     *
     * @param string $roleName The role name
     * @param string|null $userId the user uuid
     * @param string|null $username the user email
     */
    public function __construct(string $roleName, ?string $userId = null, ?string $username = null)
    {
        if (isset($userId) && !Validation::uuid($userId)) {
            throw new InternalErrorException('Invalid UserControl user id.');
        }
        if (isset($username) && !EmailValidationRule::check($username)) {
            throw new InternalErrorException('Invalid UserControl username.');
        }
        $this->userId = $userId;
        $this->roleName = $roleName;
        $this->username = $username;
    }

    /**
     * Get the user id
     *
     * @return string|null
     */
    public function getId(): ?string
    {
        return $this->userId;
    }

    /**
     * Get the user role name

View on GitHub (pinned to 31c1bbc10f)