{"record":{"id":"adcefcc767ce2443","repo":"passbolt/passbolt_api","slug":"the-role-could-not-be-updated","errorCode":null,"errorMessage":"The role could not be updated.","messagePattern":"The role could not be updated\\.","errorType":"validation","errorClass":"CustomValidationException","httpStatus":400,"severity":"error","filePath":"src/Service/Roles/RolesUpdateService.php","lineNumber":68,"sourceCode":"     * @param \\App\\Utility\\UserAccessControl $uac UAC object.\n     * @param string $roleId Role identifier to update.\n     * @param array $data Data to save.\n     * @return \\App\\Model\\Entity\\Role\n     */\n    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.","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/src/Service/Roles/RolesUpdateService.php#L50-L86","documentation":"RolesUpdateService::update throws this CustomValidationException when the edited role entity fails model validation during saveOrFail (PersistenceFailedException). The entity errors are embedded so the API consumer sees exactly which field was rejected.","triggerScenarios":"PUT /roles/{id} with a new name that violates Roles table rules: empty name, name longer than 255 characters, or uniqueness rule violation (renaming a role to an existing role's name).","commonSituations":"Renaming a role to a name that already exists, submitting a blank name from a UI that allowed empty input, or overly long names pasted from external sources.","solutions":["Check the `errors` object in the 400 response for the failing field.","Ensure the new role name is unique among existing roles (GET /roles).","Send a non-empty name within the length limit.","Retry PUT /roles/{id} with a corrected payload."],"exampleFix":"// before\nPUT /roles/<id> {\"name\": \"editor\"} // duplicate -> 400\n// after\nPUT /roles/<id> {\"name\": \"editor-v2\"} -> 200","handlingStrategy":"validation","validationCode":"const existing = await api.listRoles();\nfunction validRename(roleId, newName, existing) {\n  return typeof newName === 'string' && newName.trim().length > 0\n    && newName.length <= 255\n    && !existing.some(r => r.id !== roleId && r.name === newName);\n}\n// abort PUT if validRename(...) is false","typeGuard":"function isRenamePayload(v) {\n  return typeof v === 'object' && v !== null && typeof v.name === 'string' && v.name.trim().length > 0;\n}","tryCatchPattern":"try {\n  await api.updateRole(roleId, { name });\n} catch (e) {\n  if (e.status === 400 && e.body?.errors?.name) {\n    // duplicate or invalid name: prompt user for a different one\n  } else throw e;\n}","preventionTips":["Check name uniqueness against GET /roles before renaming","Require non-empty names and cap length at 255 chars","Trim whitespace client-side before submitting","Surface per-field errors from 400 responses in the UI"],"tags":["roles","validation","update","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"}