passbolt/passbolt_api · critical · InternalErrorException

Could not update the role, please try again later.

Error message

Could not update the role, please try again later.

What it means

RolesUpdateService::update converts any generic Exception thrown while saving the role into this InternalErrorException, preserving the original as the previous exception. It denotes an unexpected server/infrastructure error, distinct from validation failure.

Solutions

  1. Retry the update after a brief pause; transient DB issues are the usual cause.
  2. Check application logs for the chained root exception.
  3. Verify database connectivity, locks, and disk space.
  4. Re-run migrations / `ddev refresh` if a schema drift is suspected.
  5. Escalate to server operators if the error persists.

Example fix

// before
PUT /roles/<id> {"name": "x"} -> 500 Could not update the role (DB down)
// after
# restore DB, retry
PUT /roles/<id> {"name": "x"} -> 200
Defensive patterns

Strategy: retry

Validate before calling

null

Type guard

null

Try / catch

try {
  await api.updateRole(roleId, payload);
} catch (e) {
  if (e.status === 500 && /could not update the role/i.test(e.message)) {
    await sleep(backoffMs); // transient DB error: retry a few times
  } else throw e;
}

Prevention

When it happens

Trigger: PUT /roles/{id} when $this->Roles->saveOrFail raises a non-persistence Exception — database connection loss, SQL error, lock wait timeout during the UPDATE.

Common situations: DB outage or restart during the request, row lock contention on the roles table, disk full on the database server, or network failures between app and DB.

Related errors


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

Appendix: source

Thrown at src/Service/Roles/RolesUpdateService.php:73

    public function update(UserAccessControl $uac, string $roleId, array $data): Role
    {
        $uac->assertIsAdmin();

        $role = $this->getRole($roleId);
        $oldName = $role->name;
        $role = $this->patchRoleEntity($role, $data, $uac);

        try {
            $result = $this->Roles->saveOrFail($role);
        } catch (PersistenceFailedException $e) { // @phpstan-ignore-line
            $errors = $e->getEntity()->getErrors();

            throw new CustomValidationException(
                __('The role could not be updated.'),
                $errors
            );
        } catch (Exception $e) {
            throw new InternalErrorException(__('Could not update the role, please try again later.'), null, $e);
        }

        $this->dispatchEvent(self::AFTER_ROLE_UPDATE_SUCCESS_EVENT_NAME, [
            'uac' => $uac,
            'role' => $result,
            'oldName' => $oldName,
        ]);

        return $result;
    }

    /**
     * @param string $roleId Role identifier to get.
     * @return \App\Model\Entity\Role
     * @throws \Cake\Http\Exception\NotFoundException If role doesn't exist in the database
     */
    private function getRole(string $roleId): Role
    {

View on GitHub (pinned to 31c1bbc10f)