{"record":{"id":"3f580fd6353ebfa4","repo":"passbolt/passbolt_api","slug":"directory-settings-are-invalid","errorCode":null,"errorMessage":"Directory settings are invalid: ","messagePattern":"Directory settings are invalid: ","errorType":"exception","errorClass":"UnexpectedValueException","httpStatus":500,"severity":"error","filePath":"plugins/PassboltEe/DirectorySync/src/Service/DirectorySettings/FixDirectorySyncLegacyFieldsMappingService.php","lineNumber":109,"sourceCode":"    /**\n     * Get and assert the directory sync settings.\n     *\n     * @param \\App\\Model\\Entity\\OrganizationSetting $directorySyncSettings The directory sync settings\n     * @return array\n     * @throws \\UnexpectedValueException If the directory sync settings are invalid\n     */\n    private function getAndAssertDirectorySyncDefaultV3FieldsMapping(OrganizationSetting $directorySyncSettings): array\n    {\n        $value = json_decode($directorySyncSettings->value, true);\n\n        if (\n            !$value\n            || !is_array($value)\n            || !isset($value['fieldsMapping'])\n            || count($value['fieldsMapping']) !== 2\n        ) {\n            $errorMessage = \"Directory settings are invalid: {$directorySyncSettings->value}\";\n            throw new UnexpectedValueException($errorMessage);\n        }\n\n        $fieldsMapping = $value['fieldsMapping'];\n        $legacyFieldsMapping = self::getLegacyFieldsMapping();\n        $v3DiffFieldsMapping = array_diff(Hash::flatten($fieldsMapping), Hash::flatten($legacyFieldsMapping));\n\n        if (!empty($v3DiffFieldsMapping)) {\n            $errorMessage = 'Customized v3 directory sync settings fields mapping are not supported: ';\n            $errorMessage .= $directorySyncSettings->value;\n            throw new UnexpectedValueException($errorMessage);\n        }\n\n        return $value;\n    }\n\n    /**\n     * Fixes fields mapping in the database for those who upgraded from v3 to v4.\n     *","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltEe/DirectorySync/src/Service/DirectorySettings/FixDirectorySyncLegacyFieldsMappingService.php#L91-L127","documentation":"getAndAssertDirectorySyncDefaultV3FieldsMapping decodes the stored directory-sync organization setting JSON and requires it to contain a fieldsMapping array of exactly 2 entries (ad and openldap). If the JSON is empty, not an array, missing fieldsMapping, or has the wrong count, it throws this UnexpectedValueException including the raw stored value. It protects the v3→v4 mapping fix from corrupt or unexpected settings.","triggerScenarios":"Running FixDirectorySyncLegacyFieldsMappingService::fix() when the organization_settings row for directory sync holds JSON that is falsy, non-array, lacks a 'fieldsMapping' key, or has fieldsMapping with a count other than 2.","commonSituations":"Settings row truncated or hand-edited directly in the database; legacy (pre-fieldsMapping) settings format from very old passbolt versions; corrupted JSON from a failed save; importing settings from another instance.","solutions":["Inspect the stored value: SELECT value FROM organization_settings WHERE property = 'directory-sync'; and confirm the JSON structure.","Re-save the directory sync settings from the passbolt admin UI (or via the settings API) to regenerate a valid payload with default fieldsMapping.","If the row is unrecoverable, delete it and reconfigure LDAP sync from scratch.","Only run the legacy-mapping fix on installs whose settings actually date from v3 (see isDirectorySyncSettingsCreatedWithV3)."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"$raw = $settings->value;\n$decoded = json_decode($raw, true);\n$valid = $decoded && is_array($decoded) && isset($decoded['fieldsMapping']) && count($decoded['fieldsMapping']) === 2;","typeGuard":"$hasDefaultFieldsMapping = fn(?OrganizationSetting $s): bool =>\n    $s && ($v = json_decode($s->value, true)) && is_array($v)\n    && isset($v['fieldsMapping']) && is_array($v['fieldsMapping']) && count($v['fieldsMapping']) === 2;","tryCatchPattern":"try {\n    (new FixDirectorySyncLegacyFieldsMappingService())->fix();\n} catch (UnexpectedValueException $e) {\n    // stored settings are corrupt/malformed — re-save settings from admin UI\n}","preventionTips":["Never hand-edit the organization_settings value column","Re-save directory sync settings via the admin UI after upgrades","Back up organization_settings before running upgrade fix services","Validate stored JSON with json_decode before running migration utilities"],"tags":["passbolt","directory-sync","organization-settings","json","validation"],"backgroundTag":"invalid-json-response","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"}