passbolt/passbolt_api · error · Cake\Http\Exception\InternalErrorException

The Email Notification Settings configs are invalid

Error message

The Email Notification Settings configs are invalid

What it means

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.

Solutions

  1. Validate that all settings values are JSON-encodable (scalars/arrays) and valid UTF-8 before calling write().
  2. Sanitize incoming data with mb_convert_encoding or JSON_INVALID_UTF8_SUBSTITUTION where appropriate.
  3. Find the offending key by json_encode-ing each key/value pair individually and checking json_last_error().
  4. Ensure no resources or recursive references are placed into the notification settings array.

Example fix

// before
$source->write($rawSettingsFromLegacyDb, $uac);

// after
$clean = array_map(fn($v) => is_scalar($v) ? mb_convert_encoding($v, 'UTF-8', 'UTF-8') : $v, $rawSettingsFromLegacyDb);
$source->write($clean, $uac);
Defensive patterns

Strategy: type-guard

Validate before calling

function isJsonEncodable(array $data): bool {
    $json = json_encode($data);
    return $json !== false && json_last_error() === JSON_ERROR_NONE;
}
if (!isJsonEncodable($settings)) { /* abort or sanitize before write() */ }

Type guard

function isEncodableSetting($v): bool { return is_scalar($v) || is_array($v) || is_null($v); }

Try / catch

try {
    $source->write($settings, $uac);
} catch (InternalErrorException $e) {
    if (str_contains($e->getMessage(), 'configs are invalid')) {
        // sanitize/UTF-8 fix data, then retry or fall back to defaults
    }
}

Prevention

When it happens

Trigger: Calling write() with $notificationSettingsData containing resources, invalid UTF-8 sequences, inf/nan floats, or deeply/recursive structures that json_encode cannot serialize.

Common situations: 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.

Understand the failure class

Background: "JSON serialization failed", "not JSON serializable", "Failed to serialize": why JSON marshaling errors happen and how to fix them — this error's family across 46 libraries.

Related errors


AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17). Data as JSON: /api/errors/5c0a87558e436f02. Report an issue: GitHub.

Appendix: source

Thrown at plugins/PassboltCe/EmailNotificationSettings/src/Utility/NotificationSettingsSource/DbEmailNotificationSettingsSource.php:55

     * DbEmailNotificationSettingsSource constructor.
     */
    public function __construct()
    {
        $this->organizationSettingsTable = TableRegistry::getTableLocator()->get('OrganizationSettings');
    }

    /**
     * @param array $notificationSettingsData Notification settings data
     * @param \App\Utility\UserAccessControl $userAccessControl Instance of user access control
     * @return void
     */
    public function write(array $notificationSettingsData, UserAccessControl $userAccessControl): void
    {
        $data = json_encode($notificationSettingsData);

        // look for invalid structured string
        if (json_last_error() != JSON_ERROR_NONE) {
            throw new InternalErrorException('The Email Notification Settings configs are invalid');
        }

        $this->organizationSettingsTable->createOrUpdateSetting(
            EmailNotificationSettings::NAMESPACE,
            $data,
            $userAccessControl
        );
    }

    /**
     * Return an array of notification settings with notification setting name as key and notification setting value as value.
     * Notification setting names must use the dotted key normalization.
     *
     * Get config setting from the database
     *
     * @return array
     * @throws \Cake\Datasource\Exception\RecordNotFoundException If a matching DB config doesn't exist
     * @throws \Cake\Http\Exception\InternalErrorException If the DB config is not valid json string

View on GitHub (pinned to 31c1bbc10f)