passbolt/passbolt_api · error · NotFoundException

AssociatedRecordExists

AssociatedRecordExists

Error message

$errors['id']['AssociatedRecordExists'] (dynamic validation error message)

What it means

Raised in add() when DirectoryIgnore->createOrFail() fails validation with the 'AssociatedRecordExists' rule on the id field. It means the referenced user/group/directory-entry does not exist in the main application tables, so an ignore row cannot be created; the controller converts this validation error into an HTTP 404 NotFoundException carrying the dynamic validation message.

Solutions

  1. Verify the entity exists first (GET /users/{uuid}, /groups/{uuid}) before marking it ignored
  2. Refresh the id from a current listing instead of a cached/stale source
  3. Check you are calling the correct environment's API for that uuid
  4. Handle 404 in the client as 'associated record missing' and resync directory entries

Example fix

// before: post with deleted user id → 404
$api->ignore('users', $deletedUserId);
// after: guard first
if ($api->userExists($userId)) { $api->ignore('users', $userId); }
Defensive patterns

Strategy: validation

Validate before calling

try {
    $api->get("/{$model}/{$id}.json");
} catch (NotFoundException $e) {
    throw new \RuntimeException("cannot ignore $model $id: record does not exist");
}

Try / catch

try {
    $api->post("/directoryignore/{$model}/{$id}.json");
} catch (NotFoundException $e) {
    // 404 with AssociatedRecordExists: referenced user/group/entry not found
    // resync directory entries or fix the uuid
}

Prevention

When it happens

Trigger: POST /directoryignore/users/{uuid} where the uuid does not match any existing Users row (same for Groups/DirectoryEntries), e.g. a deleted entity id or a fabricated uuid.

Common situations: Syncing stale directory data whose linked passbolt user was deleted; ids taken from an old export; mixing uuids across environments (staging vs production); typos when hand-crafting requests.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/55d0046b16816f88. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltEe/DirectorySync/src/Controller/DirectoryIgnoreController.php:134

     * @return void
     */
    public function add(string $foreignModel, string $foreignKey): void
    {
        if ($this->User->role() !== Role::ADMIN) {
            throw new ForbiddenException(__('You are not authorized to access that location.'));
        }
        $this->assertDirectoryEnabled();
        $foreignModel = $this->normalizeForeignModel($foreignModel);
        if (!Validation::inList($foreignModel, ['Groups', 'Users', 'DirectoryEntries'])) {
            throw new BadRequestException(__('The record model is not valid.'));
        }

        try {
            $ignored = $this->DirectoryIgnore->createOrFail($foreignModel, $foreignKey);
        } catch (ValidationException $exception) {
            $errors = $exception->getEntity()->getErrors();
            if (isset($errors['id']['AssociatedRecordExists'])) {
                throw new NotFoundException($errors['id']['AssociatedRecordExists']);
            }
            throw $exception;
        }
        $this->success(__('The record will be ignored in the next directory synchronization.'), $ignored);
    }

    /**
     * Delete
     *
     * @param string $foreignModel foreign model
     * @param string $foreignKey foreign key
     * @return void
     */
    public function delete(string $foreignModel, string $foreignKey): void
    {
        if ($this->User->role() !== Role::ADMIN) {
            throw new ForbiddenException(__('You are not authorized to access that location.'));
        }

View on GitHub (pinned to 31c1bbc10f)