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

  1. Pass a valid UUID string (36-char canonical form) or omit the argument entirely (null) so the isset() check is skipped.
  2. Normalize the incoming id before constructing: trim whitespace, strip braces, lowercase, and validate with Validation::uuid($parentId) yourself.
  3. If the parent id comes from a previous DirectoryReports run, fetch it from the reports table rather than hardcoding/transcribing it.
  4. Trace the call site generating the id — it may be producing non-UUID task identifiers that must be fixed at the source.
  5. 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

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


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 the

View on GitHub (pinned to 31c1bbc10f)