{"record":{"id":"5c0a87558e436f02","repo":"passbolt/passbolt_api","slug":"the-email-notification-settings-configs-are-invalid","errorCode":null,"errorMessage":"The Email Notification Settings configs are invalid","messagePattern":"The Email Notification Settings configs are invalid","errorType":"http","errorClass":"Cake\\Http\\Exception\\InternalErrorException","httpStatus":500,"severity":"error","filePath":"plugins/PassboltCe/EmailNotificationSettings/src/Utility/NotificationSettingsSource/DbEmailNotificationSettingsSource.php","lineNumber":55,"sourceCode":"     * DbEmailNotificationSettingsSource constructor.\n     */\n    public function __construct()\n    {\n        $this->organizationSettingsTable = TableRegistry::getTableLocator()->get('OrganizationSettings');\n    }\n\n    /**\n     * @param array $notificationSettingsData Notification settings data\n     * @param \\App\\Utility\\UserAccessControl $userAccessControl Instance of user access control\n     * @return void\n     */\n    public function write(array $notificationSettingsData, UserAccessControl $userAccessControl): void\n    {\n        $data = json_encode($notificationSettingsData);\n\n        // look for invalid structured string\n        if (json_last_error() != JSON_ERROR_NONE) {\n            throw new InternalErrorException('The Email Notification Settings configs are invalid');\n        }\n\n        $this->organizationSettingsTable->createOrUpdateSetting(\n            EmailNotificationSettings::NAMESPACE,\n            $data,\n            $userAccessControl\n        );\n    }\n\n    /**\n     * Return an array of notification settings with notification setting name as key and notification setting value as value.\n     * Notification setting names must use the dotted key normalization.\n     *\n     * Get config setting from the database\n     *\n     * @return array\n     * @throws \\Cake\\Datasource\\Exception\\RecordNotFoundException If a matching DB config doesn't exist\n     * @throws \\Cake\\Http\\Exception\\InternalErrorException If the DB config is not valid json string","sourceCodeStart":37,"sourceCodeEnd":73,"githubUrl":"https://github.com/passbolt/passbolt_api/blob/31c1bbc10f32808a607fa9bd81891e898779c0bc/plugins/PassboltCe/EmailNotificationSettings/src/Utility/NotificationSettingsSource/DbEmailNotificationSettingsSource.php#L37-L73","documentation":"An InternalErrorException thrown by DbEmailNotificationSettingsSource::write when json_encode() of the notification settings array fails (json_last_error() != JSON_ERROR_NONE). It indicates the server could not serialize the settings for storage in the organization settings table, i.e. malformed internal data such as invalid UTF-8 or recursive structures.","triggerScenarios":"Calling write() with $notificationSettingsData containing resources, invalid UTF-8 sequences, inf/nan floats, or deeply/recursive structures that json_encode cannot serialize.","commonSituations":"Settings values imported from non-UTF-8 sources (e.g. latin1 database content or mis-encoded files); a plugin inserting a non-serializable value into the settings array; custom code calling DbEmailNotificationSettingsSource directly with unvalidated data.","solutions":["Validate that all settings values are JSON-encodable (scalars/arrays) and valid UTF-8 before calling write().","Sanitize incoming data with mb_convert_encoding or JSON_INVALID_UTF8_SUBSTITUTION where appropriate.","Find the offending key by json_encode-ing each key/value pair individually and checking json_last_error().","Ensure no resources or recursive references are placed into the notification settings array."],"exampleFix":"// before\n$source->write($rawSettingsFromLegacyDb, $uac);\n\n// after\n$clean = array_map(fn($v) => is_scalar($v) ? mb_convert_encoding($v, 'UTF-8', 'UTF-8') : $v, $rawSettingsFromLegacyDb);\n$source->write($clean, $uac);","handlingStrategy":"type-guard","validationCode":"function isJsonEncodable(array $data): bool {\n    $json = json_encode($data);\n    return $json !== false && json_last_error() === JSON_ERROR_NONE;\n}\nif (!isJsonEncodable($settings)) { /* abort or sanitize before write() */ }","typeGuard":"function isEncodableSetting($v): bool { return is_scalar($v) || is_array($v) || is_null($v); }","tryCatchPattern":"try {\n    $source->write($settings, $uac);\n} catch (InternalErrorException $e) {\n    if (str_contains($e->getMessage(), 'configs are invalid')) {\n        // sanitize/UTF-8 fix data, then retry or fall back to defaults\n    }\n}","preventionTips":["Ensure all settings values are valid UTF-8 before persisting.","Never place resources, closures, or recursive structures in the settings array.","Add a unit test that round-trips settings through json_encode/json_decode.","Prefer building settings through the form/DTO layer rather than raw arrays from external sources."],"tags":["json","serialization","internal-error","settings"],"backgroundTag":"json-serialization-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"}