{"record":{"id":"afa7c771440f1d33","repo":"passbolt/passbolt_api","slug":"msg","errorCode":null,"errorMessage":"$msg","messagePattern":"\\$msg","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"plugins/PassboltEe/DirectorySync/src/Command/SyncCommandTrait.php","lineNumber":101,"sourceCode":"        );\n        $io->out();\n    }\n\n    /**\n     * Display report\n     *\n     * @param \\Passbolt\\DirectorySync\\Actions\\Reports\\ActionReport $report report\n     * @param \\Cake\\Console\\ConsoleIo $io Console IO.\n     * @return void\n     */\n    protected function displayReport(ActionReport $report, ConsoleIo $io): void\n    {\n        $msg = str_pad('[' . $report->getStatus() . ']', $this->pad);\n        $msg .= $report->getMessage();\n        $data = $report->getData();\n        switch ($report->getStatus()) {\n            case Alias::STATUS_ERROR:\n                $io->err($msg);\n                if ($data instanceof SyncError) {\n                    $exception = $data->getException();\n                    if ($exception instanceof ValidationException) {\n                        $this->displayValidationError($exception->getErrors(), $io);\n                        $id = $exception->getEntity()->get('id');\n                        $model = $this->model;\n                    } else {\n                        $id = $data->getEntity()->get('id');\n                        $model = 'DirectoryEntries';\n                    }\n\n                    $p = str_pad('', $this->pad);\n                    $io->out($p . __('To ignore this error in the next sync please run'));\n                    $io->out($p . \"./bin/cake directory_sync ignore_create --id=$id --model=$model\");\n                }\n                break;\n            case Alias::STATUS_SYNC:\n            case Alias::STATUS_SUCCESS:","sourceCodeStart":83,"sourceCodeEnd":119,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/DirectorySync/src/Command/SyncCommandTrait.php#L83-L119","documentation":"SyncCommandTrait::displayReport() formats one line of the directory-sync report: a padded [STATUS] tag plus the report message, printed via $io->err($msg). For STATUS_ERROR reports carrying a SyncError, it further inspects the underlying exception and, for ValidationException, displays the validation errors. This output is the human-readable per-item failure line during `passbolt directory_sync`.","triggerScenarios":"Running a directory sync that produced error-status report entries — e.g. an LDAP user/group failed to create, update, or delete in passbolt because of validation errors or save failures during DirectorySync processing.","commonSituations":"Syncing LDAP entries whose data violates passbolt rules (invalid email, missing username, deleted users); conflicts between LDAP directory entries and existing passbolt records; duplicate usernames/emails from the directory.","solutions":["Read the [ERROR] line's report message to identify the failing entity and action.","For ValidationException cases, inspect the displayed per-field validation errors.","Fix the source data in LDAP (e.g. malformed email) or the conflicting passbolt record.","Re-run the sync after corrections; check the DirectorySync error reports in the admin UI for history.","Use the ignore command to skip permanently unfixable directory entries."],"exampleFix":"// before\n$msg = str_pad('[' . $report->getStatus() . ']', $this->pad);\n$msg .= $report->getMessage();\n// after\n$msg = str_pad('[' . $report->getStatus() . ']', $this->pad);\n$msg .= $report->getMessage();\nif ($report->getStatus() === Alias::STATUS_ERROR && $report->getData() instanceof SyncError) {\n    $msg .= ' (entity: ' . ($report->getData()->getEntity()->id ?? 'n/a') . ')';\n}","handlingStrategy":"validation","validationCode":"// pre-validate directory data before sync so reports stay clean\n$errors = $Users->newEntity($ldapUserData)->getErrors();\nif ($errors) {\n    // fix LDAP-sourced fields (email, username, profile) before running sync\n    var_dump($errors);\n}","typeGuard":"function hasSyncableData($report): bool {\n    $data = $report->getData();\n    return !$data instanceof \\Passbolt\\DirectorySync\\Model\\Entity\\SyncError\n        || !($data->getException() instanceof \\Cake\\Datasource\\Validation\\ValidationException);\n}","tryCatchPattern":"// reports are aggregated, not thrown — handle error-status reports after sync\nforeach ($reports as $report) {\n    if ($report->getStatus() === \\Passbolt\\DirectorySync\\Model\\Utility\\SyncAction::STATUS_ERROR) {\n        $this->displayReport($report, $io);\n    }\n}","preventionTips":["Clean LDAP data (emails, usernames) before syncing to avoid validation errors.","Resolve conflicts between directory entries and existing passbolt users first.","Review the sync report after every run and fix [ERROR] items promptly.","Use the ignore command for directory entries that can never pass validation."],"tags":["ldap","directory-sync","cli","sync-report","validation"],"backgroundTag":"schema-validation-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"}