passbolt/passbolt_api · error · InternalErrorException

Could not save the action log.

Error message

Could not save the action log.

What it means

ActionLogsTable::create() throws this InternalErrorException when the action log entity passes validation but the subsequent save() call returns false (or null). It signals an unexpected persistence failure that is not a validation problem — e.g. a database connectivity issue, schema mismatch, or a save callback aborting the write.

Solutions

  1. Check the database connectivity and error logs (CakePHP error.log) for the underlying save failure.
  2. Run pending migrations (passbolt migrate / bin/cake migrations migrate) so the action_logs schema matches the code.
  3. Temporarily wrap the save with error inspection (e.g. check connection->lastError or logs) to find the failing constraint or callback.
  4. Verify no custom plugin beforeSave rules abort saving action logs.
  5. severity_check: confirm the table's connection is healthy and disk space is available.

Example fix

// before
$logSaved = $this->save($log);
if (!$logSaved) {
    throw new InternalErrorException('Could not save the action log.');
}
// after
$logSaved = $this->save($log);
if (!$logSaved) {
    $this->log(
        'Action log save failed: ' . json_encode($log->getErrors()),
        'error'
    );
    throw new InternalErrorException('Could not save the action log.');
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!$entity instanceof \Passbolt\Log\Model\Entity\ActionLog) { throw new \InvalidArgumentException('Expected ActionLog entity'); }

Type guard

function isValidActionLogData(array $data): bool { return isset($data['status']) && is_int($data['status']); }

Try / catch

try { $logsService->create($data); } catch (InternalErrorException $e) { // check DB health, alert, do not fail the user request for logging issues
    Log::error('Action log persistence failed: ' . $e->getMessage());
}

Prevention

When it happens

Trigger: Calling ActionLogsTable::create() with data that validates but fails at the database layer: DB connection dropped mid-request, missing action_logs table/column after incomplete migration, duplicate-key or integrity constraint violation surfaced through events rather than validation, or a Model.beforeSave rule returning false.

Common situations: Production environments where migrations were not run after a passbolt upgrade; disk-full or DB-max-connections conditions; custom plugins attaching beforeSave/beforeMarshal callbacks that silently abort log persistence.

Related errors


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

Appendix: source

Thrown at plugins/PassboltCe/Log/src/Model/Table/ActionLogsTable.php:156

            'status' => $status,
        ];
        // Check validation rules.
        $log = $this->buildEntity($data);
        if ($log->getErrors()) {
            throw new ValidationException(__('Could not validate action log data.'), $log, $this);
        }

        /** @var \Passbolt\Log\Model\Entity\ActionLog|bool $logSaved */
        $logSaved = $this->save($log);

        // Check for validation errors. (associated models too).
        if ($log->getErrors()) {
            throw new ValidationException(__('Could not validate action log data.'), $log, $this);
        }

        // Check for errors while saving.
        if (!$logSaved) {
            throw new InternalErrorException('Could not save the action log.');
        }

        return $logSaved;
    }

    /**
     * Return a action_log entity.
     *
     * @param array $data entity data
     * @return \Passbolt\Log\Model\Entity\ActionLog
     */
    public function buildEntity(array $data): ActionLog
    {
        return $this->newEntity($data, [
            'accessibleFields' => [
                'id' => true,
                'user_id' => true,
                'action_id' => true,

View on GitHub (pinned to 31c1bbc10f)