passbolt/passbolt_api · error
Unable to retrieve the migration…
Error message
Unable to retrieve the migration V400ChangeLdapServersConfigKey.
What it means
FixDirectorySyncLegacyFieldsMappingService::fix() determines whether directory sync settings were created under passbolt v3 by looking up the phinxlog row for migration V400ChangeLdapServersConfigKey. If no such migration record exists in the phinxlog table it throws this Exception, since it cannot date the settings without it.
Solutions
- Run pending migrations (bin/cake passbolt migrate or ddev refresh) so V400ChangeLdapServersConfigKey is recorded in phinxlog.
- Verify with SQL: SELECT * FROM phinxlog WHERE migration_name = 'V400ChangeLdapServersConfigKey';
- If settings were created on v4 (migration genuinely absent), this check is irrelevant — ensure the fix only runs for true v3 upgrades, or skip fix() when no settings exist.
- Do not hand-delete phinxlog rows; restore from a consistent backup if phinxlog is corrupted.
Example fix
// shell # before: running fix on unmigrated DB fails bin/cake passbolt migrate # after: migration recorded, fix() can resolve the migration end_time
Defensive patterns
Strategy: validation
Validate before calling
$row = $phinxlog->find()->where(['migration_name' => 'V400ChangeLdapServersConfigKey'])->first();
if (!$row) { bin/cake passbolt migrate; } Type guard
$migrationApplied = fn(Table $phinxlog): bool => (bool)$phinxlog->find()->where(['migration_name' => 'V400ChangeLdapServersConfigKey'])->first();
Try / catch
try {
(new FixDirectorySyncLegacyFieldsMappingService())->fix();
} catch (Exception $e) {
// run passbolt migrate, then retry the fix
} Prevention
- Always complete migrations (passbolt migrate) before running upgrade fix services
- Never manually delete rows from phinxlog
- Keep phinxlog and schema in sync when restoring backups (restore code + DB together)
- Gate the legacy-mapping fix to installs that actually had the v3 migration
When it happens
Trigger: Running the legacy fields-mapping fix (part of v3→v4 upgrade maintenance) on an install whose phinxlog table lacks the row migration_name='V400ChangeLdapServersConfigKey' — e.g. migrations were never run, run partially, or the row was manually removed.
Common situations: Upgrading passbolt without executing all migrations (skipped ddev refresh / passbolt migrate); restoring a DB dump while phinxlog was out of sync; fresh v4 install that never had the v3 migration but has directory settings copied over; manually pruning phinxlog rows.
Understand the failure class
Background: Record Not Found Errors: "not found", RecordNotFound, and "was not found" — what they mean and how to fix them — this error's family across 28 libraries.
Related errors
- Invalid phinxlog migration entity, end_time property not…
- Directory Settings are invalid. Please check your config…
- Could not ignore the record, please try again later.
- Customized v3 directory sync settings fields mapping are…
- Directory settings are invalid:
AI-assisted analysis of passbolt/passbolt_api@31c1bbc10f (2026-09-17).
Data as JSON: /api/errors/5b14d2177bcd602f.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/PassboltEe/DirectorySync/src/Service/DirectorySettings/FixDirectorySyncLegacyFieldsMappingService.php:82
}
/**
* Check if the directory sync settings were created with a v3.
*
* @param \App\Model\Entity\OrganizationSetting $directorySyncSetting The directory sync settings
* @return bool
* @throws \Exception If the migration V400ChangeLdapServersConfigKey cannot be found
* @throws \Exception If the migration V400ChangeLdapServersConfigKey format is invalid
*/
private function isDirectorySyncSettingsCreatedWithV3(OrganizationSetting $directorySyncSetting): bool
{
/** @var \Cake\ORM\Entity|null $migration */
$migration = $this->phinxlogTable->find()
->where(['migration_name' => 'V400ChangeLdapServersConfigKey'])
->first();
if (is_null($migration)) {
throw new Exception('Unable to retrieve the migration V400ChangeLdapServersConfigKey.');
}
if (property_exists($migration, 'end_time')) {
throw new Exception('Invalid phinxlog migration entity, end_time property not defined.');
}
return $directorySyncSetting->created->lessThan($migration->get('end_time'));
}
/**
* Get and assert the directory sync settings.
*
* @param \App\Model\Entity\OrganizationSetting $directorySyncSettings The directory sync settings
* @return array
* @throws \UnexpectedValueException If the directory sync settings are invalid
*/
private function getAndAssertDirectorySyncDefaultV3FieldsMapping(OrganizationSetting $directorySyncSettings): array
{
$value = json_decode($directorySyncSettings->value, true);View on GitHub (pinned to 31c1bbc10f)