{"record":{"id":"4114c83c3edefa55","repo":"passbolt/passbolt_api","slug":"user-could-not-be-updated","errorCode":null,"errorMessage":"User could not be updated.","messagePattern":"User could not be updated\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"plugins/PassboltEe/DirectorySync/src/Actions/UserSyncAction.php","lineNumber":144,"sourceCode":"    /**\n     * Update user\n     *\n     * @param \\App\\Model\\Entity\\User $existingUser User\n     * @param array $data data\n     * @return void\n     */\n    private function updateUser(User $existingUser, array $data): void\n    {\n        try {\n            $user = $this->Users->editEntity($existingUser, $data, new UserAccessControl(Role::ADMIN));\n            $result = $this->Users->save($user, ['checkrules' => false]);\n\n            if (!$result) {\n                if ($user->hasErrors()) {\n                    $msg = __('Could not validate user data.');\n                    throw new ValidationException($msg, $user, $this->Users);\n                }\n                throw new Exception('User could not be updated.');\n            }\n            // Send report.\n            $this->addReportItem(new ActionReport(\n                __(\n                    'The user {0} full name has been successfully updated to {1} {2}.',\n                    $existingUser->username,\n                    $user->profile->first_name,\n                    $user->profile->last_name\n                ),\n                Alias::MODEL_USERS,\n                Alias::ACTION_UPDATE,\n                Alias::STATUS_SUCCESS,\n                $user\n            ));\n        } catch (Exception $exception) {\n            $error = new SyncError($existingUser, $exception);\n            $this->addReportItem(new ActionReport(\n                __(","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/DirectorySync/src/Actions/UserSyncAction.php#L126-L162","documentation":"This generic Exception is thrown by UserSyncAction::updateUser when the Users table save() call returns false but the entity carries no validation errors, so the sync action cannot report a precise cause. It is a last-resort fallback in the LDAP directory-sync user-update flow: the persistence layer failed for a reason outside field validation (e.g. database error, event listener aborting the save). Because the message carries no entity or SQL detail, debugging requires inspecting server logs.","triggerScenarios":"Running `passbolt directory_sync` sync where an existing user matched from the LDAP directory has changed attributes (e.g. full name) and $this->Users->save($user) returns false with $user->hasErrors() === false. Typical concrete causes: a beforeSave/afterSave rule failing silently, a database constraint violation, or a model event listener calling stopPropagation/aborting the save without setting entity errors.","commonSituations":"AD/LDAP sync updating a user whose data passes entity validation but breaks at the database level (e.g. NULL in a non-null column introduced by a plugin hook); corrupted users table row; custom plugin event listeners on Model.beforeSave that block saves; MySQL/Postgres constraint mismatch after a partial migration.","solutions":["Check passbolt error logs (logs/error.log) for the underlying database or event-listener error at the time of the sync run.","Re-run the sync with debug enabled or inspect $user->getErrors() and the save() return path in UserSyncAction to identify why save() failed without validation errors.","Verify the users table schema matches migrations: run `ddev refresh` / `passbolt migrate` to ensure no stale constraints.","Disable third-party plugins hooking into Users model events to rule out a listener aborting the save, then re-run sync."],"exampleFix":"// before: silent fallback hides the cause\nthrow new Exception('User could not be updated.');\n// after: surface the underlying save failure\n$err = $this->Users->getConnection()->errorInfo ?? null;\nthrow new Exception('User could not be updated. Save failed' . ($err ? ': ' . json_encode($err) : '.') . ' User id: ' . $existingUser->id);","handlingStrategy":"try-catch","validationCode":"if (!$user->getErrors() && !$this->Users->save($user)) {\n    error_log('User save failed for id ' . $existingUser->id . ' errors: ' . json_encode($user->getErrors()));\n}","typeGuard":null,"tryCatchPattern":"try {\n    $syncService->updateUser($user, $entry);\n} catch (ValidationException $e) {\n    // entity-level issues\n} catch (Exception $e) {\n    if ($e->getMessage() === 'User could not be updated.') {\n        // inspect server logs / retry save manually to find root cause\n    }\n}","preventionTips":["Validate user data with the Users table validator before attempting the sync save.","Keep model event listeners (plugins) tested so they never abort save() without setting errors.","Keep migrations up to date so no stale DB constraints fail saves silently.","Monitor logs/error.log during sync runs."],"tags":["directory-sync","ldap","user-update","persistence"],"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"}