{"record":{"id":"d40fb0b9c8e440ab","repo":"passbolt/passbolt_api","slug":"could-not-update-the-role-please-try-again-later","errorCode":null,"errorMessage":"Could not update the role, please try again later.","messagePattern":"Could not update the role, please try again later\\.","errorType":"http","errorClass":"InternalErrorException","httpStatus":500,"severity":"critical","filePath":"src/Service/Roles/RolesUpdateService.php","lineNumber":73,"sourceCode":"    public function update(UserAccessControl $uac, string $roleId, array $data): Role\n    {\n        $uac->assertIsAdmin();\n\n        $role = $this->getRole($roleId);\n        $oldName = $role->name;\n        $role = $this->patchRoleEntity($role, $data, $uac);\n\n        try {\n            $result = $this->Roles->saveOrFail($role);\n        } catch (PersistenceFailedException $e) { // @phpstan-ignore-line\n            $errors = $e->getEntity()->getErrors();\n\n            throw new CustomValidationException(\n                __('The role could not be updated.'),\n                $errors\n            );\n        } catch (Exception $e) {\n            throw new InternalErrorException(__('Could not update the role, please try again later.'), null, $e);\n        }\n\n        $this->dispatchEvent(self::AFTER_ROLE_UPDATE_SUCCESS_EVENT_NAME, [\n            'uac' => $uac,\n            'role' => $result,\n            'oldName' => $oldName,\n        ]);\n\n        return $result;\n    }\n\n    /**\n     * @param string $roleId Role identifier to get.\n     * @return \\App\\Model\\Entity\\Role\n     * @throws \\Cake\\Http\\Exception\\NotFoundException If role doesn't exist in the database\n     */\n    private function getRole(string $roleId): Role\n    {","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/src/Service/Roles/RolesUpdateService.php#L55-L91","documentation":"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.","triggerScenarios":"PUT /roles/{id} when $this->Roles->saveOrFail raises a non-persistence Exception — database connection loss, SQL error, lock wait timeout during the UPDATE.","commonSituations":"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.","solutions":["Retry the update after a brief pause; transient DB issues are the usual cause.","Check application logs for the chained root exception.","Verify database connectivity, locks, and disk space.","Re-run migrations / `ddev refresh` if a schema drift is suspected.","Escalate to server operators if the error persists."],"exampleFix":"// before\nPUT /roles/<id> {\"name\": \"x\"} -> 500 Could not update the role (DB down)\n// after\n# restore DB, retry\nPUT /roles/<id> {\"name\": \"x\"} -> 200","handlingStrategy":"retry","validationCode":"null","typeGuard":"null","tryCatchPattern":"try {\n  await api.updateRole(roleId, payload);\n} catch (e) {\n  if (e.status === 500 && /could not update the role/i.test(e.message)) {\n    await sleep(backoffMs); // transient DB error: retry a few times\n  } else throw e;\n}","preventionTips":["Monitor database connectivity and locks on the roles table","Avoid schema drift; keep migrations current","Log chained exceptions server-side for diagnosis","Apply bounded exponential backoff on 500 responses"],"tags":["internal-error","database","roles","passbolt"],"backgroundTag":"database-write-failed","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"}