Leantime/leantime · error · Leantime\Core\Exceptions\EntityExistsException

-32005

-32005

Error message

Client exists already

What it means

createClient() calls isClient($values) (which delegates to the repository) to check whether a client with the same name/street combination already exists; if so it throws EntityExistsException, mapped to JSON-RPC code -32005. isClient() is itself an @api method, so callers can pre-check for duplicates before attempting the create.

Source

Thrown at app/Domain/Clients/Services/Clients.php:234

     * that previously lived in the controller.
     *
     * @param  array  $values  Client data to create (requires a non-empty 'name')
     * @return int Id of the newly created client
     *
     * @throws MissingParameterException When the client name is empty
     * @throws EntityExistsException When a client with the same name/street already exists
     *
     * @api
     */
    #[RequiresPermission(ClientsPermissions::CREATE, global: true)]
    public function createClient(array $values): int
    {
        if (($values['name'] ?? '') === '') {
            throw new MissingParameterException('Client name not specified');
        }

        if ($this->isClient($values) === true) {
            throw new EntityExistsException('Client exists already');
        }

        return (int) $this->clientRepository->addClient($values);
    }

    /**
     * Updates an existing client after validating the name is present.
     *
     * @param  array  $values  Client data including 'id' key (requires a non-empty 'name')
     * @return bool Returns true on success, false on failure
     *
     * @throws MissingParameterException When the client name is empty
     *
     * @api
     */
    #[RequiresPermission(ClientsPermissions::EDIT, global: true)]
    public function updateClient(array $values): bool
    {

View on GitHub (pinned to 9a9f49f100)

Solutions

  1. Pre-check with leantime.rpc.Clients.Clients.isClient using the same payload; if it returns true, call updateClient on the existing client instead of creating
  2. Make the client name unique (or correct the street value) if the duplicate is unintentional
  3. Protect the UI against double submits (disable the button / POST-redirect-GET) and catch EntityExistsException (-32005) to show a friendly 'already exists' message

Example fix

// before
$newId = $clientsService->createClient($values);

// after
if ($clientsService->isClient($values)) {
    throw new \RuntimeException('Client already exists; use updateClient');
}
$newId = $clientsService->createClient($values);
Defensive patterns

Strategy: validation

Validate before calling

if ($clientsService->isClient($values)) {
    // duplicate name/street — update the existing client instead of creating
    $existing = $clientsService->getAll();
    // ...find and update, or prompt the user
}

Try / catch

try {
    $id = $clientsService->createClient($values);
} catch (\Leantime\Core\Exceptions\EntityExistsException $e) {
    // JSON-RPC -32005: offer 'edit existing client' instead of create
    $form->addError('name', 'A client with this name/street already exists');
}

Prevention

When it happens

Trigger: Calling createClient with a name+street combination that matches an existing zp_clients row; double-submitting the create form (second POST arrives after the first succeeded); retrying an API call after a timeout when the first attempt actually committed.

Common situations: Create forms without POST-redirect-GET or a disabled submit button; re-running a data import script that is not idempotent; two users creating the same client name concurrently.

Related errors


AI-assisted analysis of Leantime/leantime@9a9f49f100 (2026-08-21). Data as JSON: /api/errors/f1c12585830edac3. Report an issue: GitHub.