passbolt/passbolt_api · error · Exception
The parent task identifier should be a valid UUID.
Error message
The parent task identifier should be a valid UUID.
What it means
SyncAction's constructor validates the optional $parentId argument with CakePHP Validation::uuid() when it is provided (isset); a non-null value that is not a valid UUID throws this generic Exception before any sync work starts. It is a fail-fast input-format guard ensuring the parent task identifier references a valid report/report-item UUID.
Solutions
- Pass a valid UUID string (36-char canonical form) or omit the argument entirely (null) so the isset() check is skipped.
- Normalize the incoming id before constructing: trim whitespace, strip braces, lowercase, and validate with Validation::uuid($parentId) yourself.
- If the parent id comes from a previous DirectoryReports run, fetch it from the reports table rather than hardcoding/transcribing it.
- Trace the call site generating the id — it may be producing non-UUID task identifiers that must be fixed at the source.
- In integrations, validate the option early (e.g. in the console command's option parser) to fail with a clearer message.
Example fix
// before
$sync = new SyncAction($parentIdFromCli); // may be '' or a non-UUID string -> Exception
// after
$parentId = trim($parentIdFromCli ?? '');
if ($parentId !== '' && !\Cake\Validation\Validation::uuid($parentId)) {
throw new \InvalidArgumentException("Invalid parent id: {$parentId}");
}
$sync = new SyncAction($parentId !== '' ? $parentId : null); Defensive patterns
Strategy: validation
Validate before calling
use Cake\Validation\Validation;
if (isset($parentId) && !Validation::uuid($parentId)) {
throw new \InvalidArgumentException('The parent task identifier should be a valid UUID.');
} Type guard
function isValidParentId($parentId): bool {
return $parentId === null || (is_string($parentId) && \Cake\Validation\Validation::uuid($parentId));
} Try / catch
try {
$sync = new SyncAction($parentId);
} catch (Exception $e) {
if (str_contains($e->getMessage(), 'valid UUID')) {
$this->abort("Invalid --parent-id value: {$parentId}");
}
throw $e;
} Prevention
- Validate CLI/option inputs with Validation::uuid() before constructing the action.
- Trim and normalize ids taken from logs or external systems (whitespace, braces, casing).
- Fetch parent report ids from the DirectoryReports table instead of manual copy/paste.
- Pass null (not '' or 0) when no parent task applies, so the isset() guard is skipped.
When it happens
Trigger: Constructing SyncAction with a parentId argument that is an empty string treated as set, a numeric id, an arbitrary string, a truncated or uppercase-braced UUID, or an id from another format/version when invoking directory sync programmatically or via command options.
Common situations: Wrappers and CLI scripts passing the parent report id from user input without validation, copying ids with surrounding whitespace or braces from logs, or passing null-coalesced placeholder values like '' or 0.
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
- Invalid user ID format.
- The identifier should be a valid UUID.
- The metadata key ID should be a valid UUID.
- The record model is not valid.
- group(s) returned by your directory are invalid and will be…
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/ba25e41b89d9a4c8.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltEe/DirectorySync/src/Actions/SyncAction.php:194
ResourcesExpireResourcesServiceInterface $resourcesExpireResourcesService,
?string $parentId = null
) {
$this->directoryOrgSettings = DirectoryOrgSettings::get();
$this->directory = DirectoryFactory::get($this->directoryOrgSettings);
$this->resourcesExpireResourcesService = $resourcesExpireResourcesService;
$this->DirectoryEntries = $this->fetchTable('Passbolt/DirectorySync.DirectoryEntries');
$this->DirectoryIgnore = $this->fetchTable('Passbolt/DirectorySync.DirectoryIgnore');
$this->DirectoryRelations = $this->fetchTable('Passbolt/DirectorySync.DirectoryRelations');
$this->DirectoryReports = $this->fetchTable('Passbolt/DirectorySync.DirectoryReports');
$this->Users = $this->fetchTable('Users');
$this->summary = new ActionReportCollection();
$this->defaultAdmin = $this->getDefaultAdmin();
if (empty($this->defaultAdmin)) {
throw new Exception('Configuration issue. A default admin user cannot be found.');
}
if (isset($parentId) && !Validation::uuid($parentId)) {
throw new Exception('The parent task identifier should be a valid UUID.');
}
$this->parentId = $parentId;
}
/**
* Execute sync.
* - Delete all entities that can be deleted
* - Create all entities that can be created
* - Generate report
*
* @return \Passbolt\DirectorySync\Actions\Reports\ActionReportCollection
*/
public function execute(): ActionReportCollection
{
$conn = $this->Users->getConnection();
// Enable savepoints so that inner transactional() calls (e.g. in GroupsUpdateService,
// GroupsUsersAddService) create real SQL savepoints. Without savepoints, CakePHP tracks
// nested rollbacks and prevents the outer transaction from committing — even when theView on GitHub (pinned to 31c1bbc10f)