passbolt/passbolt_api · error · BadRequestException
The user id is invalid.
Error message
The user id is invalid.
What it means
BadRequestException thrown by AccountRecoveryContinueController::get() when the userId route parameter is missing or not a valid UUID. The controller validates all identifier parameters before delegating to services.
Solutions
- Regenerate the recovery link ensuring the full user UUID is included
- Validate the user id is a UUID before making the request (Cake\Validation::uuid())
- Check the email template/link builder produces the correct route
- Log the incoming URL to confirm which parameter is malformed
Example fix
// before
$url = "/account-recovery/continue/$userId/$tokenId.json"; // $userId = 'admin@example.com'
// after
$user = $usersTable->findByUsername($email)->firstOrFail();
$url = "/account-recovery/continue/{$user->id}/$tokenId.json"; Defensive patterns
Strategy: validation
Validate before calling
import { uuidValidation } from 'passbolt/styleguide/lib/assertions/uuid.validation';
if (!uuidValidation(userId)) throw new Error('user id must be a UUID'); Type guard
function isValidUuid(value: unknown): value is string {
return typeof value === 'string'
&& /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
} Try / catch
try {
await accountRecoveryContinueService.get(userId, tokenId);
} catch (ApiError e) {
if (e.message.includes('user id is invalid')) {
redirectToRecoveryStart(); // regenerate a valid link
}
} Prevention
- Always build recovery URLs from the entity's UUID field, never username/email
- Validate identifiers with Validation::uuid() client-side before navigation
- Escape/log full recovery URLs when debugging email links
- Ensure route parameters are not truncated by URL builders
When it happens
Trigger: GET request to the account recovery continue endpoint with a missing, empty, or malformed (non-UUID) user id in the URL, e.g. /account-recovery/continue/not-a-uuid/<token-id>.json
Common situations: Broken or hand-edited recovery link from an email template; truncated URL; client sending a username/email instead of the user UUID; old links generated before ID format changes.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- The authentication token id is invalid.
- The request data is invalid: id invalid.
- The user id is invalid.
- " " is not a valid search filter.
- " " is not a valid search filter. It is not a UTF8 string.
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/e42eceaaea193ee2.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltEe/AccountRecovery/src/Controller/AccountRecoveryContinue/AccountRecoveryContinueController.php:63
parent::beforeFilter($event);
}
/**
* Render a page to continue the account recovery process
*
* @param string|null $userId User ID
* @param string|null $tokenId Token ID
* @param \Passbolt\Ee\Service\AccountRecoveryContinue\AccountRecoveryContinueAggregatorService $accountRecoveryContinueService Service instance.
* @return void
* @throws \Cake\Http\Exception\BadRequestException if the data provided is not valid
*/
public function get(
?string $userId,
?string $tokenId,
AccountRecoveryContinueAggregatorService $accountRecoveryContinueService
): void {
if (!isset($userId) || !Validation::uuid($userId)) {
throw new BadRequestException(__('The user id is invalid.'));
}
if (!isset($tokenId) || !Validation::uuid($tokenId)) {
throw new BadRequestException(__('The authentication token id is invalid.'));
}
if ($this->getRequest()->is('json')) {
// Do not allow logged in user to recover
if ($this->User->role() !== Role::GUEST) {
throw new ForbiddenException(__('Only guests are allowed to proceed with account recovery.'));
}
(new AccountRecoveryRequestGetService())->getOrFail($userId, $tokenId);
$data = $accountRecoveryContinueService->get();
$this->success(__('The operation was successful.'), $data);
} else {
$this->renderHtml();View on GitHub (pinned to 31c1bbc10f)