{"record":{"id":"ba25e41b89d9a4c8","repo":"passbolt/passbolt_api","slug":"the-parent-task-identifier-should-be-a-valid-uuid","errorCode":null,"errorMessage":"The parent task identifier should be a valid UUID.","messagePattern":"The parent task identifier should be a valid UUID\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"plugins/PassboltEe/DirectorySync/src/Actions/SyncAction.php","lineNumber":194,"sourceCode":"        ResourcesExpireResourcesServiceInterface $resourcesExpireResourcesService,\n        ?string $parentId = null\n    ) {\n        $this->directoryOrgSettings = DirectoryOrgSettings::get();\n        $this->directory = DirectoryFactory::get($this->directoryOrgSettings);\n        $this->resourcesExpireResourcesService = $resourcesExpireResourcesService;\n\n        $this->DirectoryEntries = $this->fetchTable('Passbolt/DirectorySync.DirectoryEntries');\n        $this->DirectoryIgnore = $this->fetchTable('Passbolt/DirectorySync.DirectoryIgnore');\n        $this->DirectoryRelations = $this->fetchTable('Passbolt/DirectorySync.DirectoryRelations');\n        $this->DirectoryReports = $this->fetchTable('Passbolt/DirectorySync.DirectoryReports');\n        $this->Users = $this->fetchTable('Users');\n        $this->summary = new ActionReportCollection();\n        $this->defaultAdmin = $this->getDefaultAdmin();\n        if (empty($this->defaultAdmin)) {\n            throw new Exception('Configuration issue. A default admin user cannot be found.');\n        }\n        if (isset($parentId) && !Validation::uuid($parentId)) {\n            throw new Exception('The parent task identifier should be a valid UUID.');\n        }\n        $this->parentId = $parentId;\n    }\n\n    /**\n     * Execute sync.\n     * - Delete all entities that can be deleted\n     * - Create all entities that can be created\n     * - Generate report\n     *\n     * @return \\Passbolt\\DirectorySync\\Actions\\Reports\\ActionReportCollection\n     */\n    public function execute(): ActionReportCollection\n    {\n        $conn = $this->Users->getConnection();\n        // Enable savepoints so that inner transactional() calls (e.g. in GroupsUpdateService,\n        // GroupsUsersAddService) create real SQL savepoints. Without savepoints, CakePHP tracks\n        // nested rollbacks and prevents the outer transaction from committing — even when the","sourceCodeStart":176,"sourceCodeEnd":212,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/DirectorySync/src/Actions/SyncAction.php#L176-L212","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\n$sync = new SyncAction($parentIdFromCli); // may be '' or a non-UUID string -> Exception\n// after\n$parentId = trim($parentIdFromCli ?? '');\nif ($parentId !== '' && !\\Cake\\Validation\\Validation::uuid($parentId)) {\n    throw new \\InvalidArgumentException(\"Invalid parent id: {$parentId}\");\n}\n$sync = new SyncAction($parentId !== '' ? $parentId : null);","handlingStrategy":"validation","validationCode":"use Cake\\Validation\\Validation;\nif (isset($parentId) && !Validation::uuid($parentId)) {\n    throw new \\InvalidArgumentException('The parent task identifier should be a valid UUID.');\n}","typeGuard":"function isValidParentId($parentId): bool {\n    return $parentId === null || (is_string($parentId) && \\Cake\\Validation\\Validation::uuid($parentId));\n}","tryCatchPattern":"try {\n    $sync = new SyncAction($parentId);\n} catch (Exception $e) {\n    if (str_contains($e->getMessage(), 'valid UUID')) {\n        $this->abort(\"Invalid --parent-id value: {$parentId}\");\n    }\n    throw $e;\n}","preventionTips":["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."],"tags":["validation","uuid","directory-sync","invalid-argument"],"backgroundTag":"invalid-argument-format","analyzedSha":"31c1bbc10f32808a607fa9bd81891e898779c0bc","analyzedAt":"2026-09-17T00:04:38.960Z","contentChangedAt":"2026-09-17T00:04:38.960Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}