Summary
During fresh Oro Platform installation (specifically when running bin/console oro:migration:load --force or bin/console oro:platform:update --force), the initialization process fails with a Doctrine QueryException when the entity config cache warmup step tries to query the Organization.is_global field. The field should have been added by the OrganizationProBundle installer, but Doctrine's extended entity metadata has not been synchronized yet, causing "field doesn't exist" semantic errors.
This is a classic initialization order race condition affecting fresh installations on PHP 8.4+ where strict type checking is enforced.
Steps to reproduce
- Start with a clean PostgreSQL database (no tables)
- Restore an Oro 6.1 EE backup from before extended entity initialization (or start from scratch)
- Ensure
var/installed marker exists to skip the web installer:
- Clear cache and proxies:
rm -rf var/cache/* var/doctrine_proxies/*
- Run migrations with verbosity to see the error:
bin/console oro:migration:load --force -vvv
Why This Step Triggers the Bug:
The oro:migration:load command executes all pending migrations. One of these migrations is WarmUpEntityConfigCacheMigration from EntityConfigBundle, which internally runs the oro:entity-config:cache:warmup command. This is a migration query, not a separate step. The error occurs during the migration sequence.
Actual Result
During step 5, the migration sequence fails at the WarmUpEntityConfigCacheMigration with:
[RuntimeException] Failed migrations: Oro\Bundle\EntityConfigBundle\Migration\WarmUpEntityConfigCacheMigration
In QueryException.php line 23:
[Doctrine\ORM\Query\QueryException]
SELECT org FROM Oro\Bundle\OrganizationBundle\Entity\Organization org WHERE org.is_global = :isGlobal
Exception trace:
at /oro-ee/vendor/doctrine/orm/lib/Doctrine/ORM/Query/QueryException.php:23
Doctrine\ORM\Query\QueryException::dqlError() at /oro-ee/vendor/doctrine/orm/lib/Doctrine/ORM/Query/Parser.php:495
...
[Semantical Error] Error: Class Oro\Bundle\OrganizationBundle\Entity\Organization has no field or association named is_global
The entire migration sequence stops, blocking the installation. No further migrations run after this failure.
Expected Result
The platform initialization should complete successfully even on fresh installations. The extended entity field is_global should either:
- Be available to query by the time entity config cache warmup runs, OR
- Be handled gracefully if not yet synchronized at that point in initialization
A fresh installation should not fail due to uninitialized extended entity metadata.
Details about your environment
- OroPlatform version: 6.1.0 EE
- OroPlatformEnterprise version: 6.1.0 EE
- PHP version: 8.4.14+ (strict type checking enforced)
- Database: PostgreSQL 13.7+
- Server operating system: Linux (Ubuntu 24.04+, Docker container)
Root Cause Analysis
The Initialization Sequence Problem
-
Migration starts: oro:migration:load command executes
-
OrganizationProBundle installer runs (via OroOrganizationProBundleInstaller.php):
- Adds
is_global column to oro_organization table (lines 48-64)
- Marks the Organization entity as "is_global aware"
- Configures extended entity metadata (ExtendScope, OroOptions, etc.)
-
Entity config cache warmup runs (via WarmUpEntityConfigCacheMigration):
- Calls
oro:entity-config:cache:warmup command
- This discovers and indexes all extended entity configurations
- Various helper classes query the Organization entity for
is_global field:
OrganizationProHelper::getGlobalOrganization() at line 54
OwnershipProConditionDataBuilder::getGlobalOrganizationId() at line 110
-
Doctrine metadata mismatch:
- The database column exists (added in step 2)
- But Doctrine's in-memory metadata hasn't been synchronized
- Doctrine still thinks Organization has no
is_global field
- DQL parser throws semantic error: "Class has no field named is_global"
Why This Happens
The extended entity metadata synchronization happens after the entity config cache is warmed up, but the code tries to query the field during warmup. This creates a race condition where:
- The schema is updated (column added)
- The Doctrine metadata is NOT updated (field not in entity class metadata yet)
- Queries fail because Doctrine doesn't know about the new field
Affected Code Files
Primary Locations (Query Failures):
-
vendor/oro/platform-enterprise/src/Oro/Bundle/OrganizationProBundle/Helper/OrganizationProHelper.php (line 54)
->where('org.is_global = :isGlobal')
-
vendor/oro/platform-enterprise/src/Oro/Bundle/SecurityProBundle/ORM/Walker/OwnershipProConditionDataBuilder.php (line 110)
->findOneBy(['is_global' => true]);
Extended Entity Definition:
vendor/oro/platform-enterprise/src/Oro/Bundle/OrganizationProBundle/Migrations/Schema/OroOrganizationProBundleInstaller.php (lines 48-64)
- Column addition with extended entity metadata
- This runs too late in the initialization sequence
Triggered By:
vendor/oro/platform/src/Oro/Bundle/EntityConfigBundle/Migration/WarmUpEntityConfigCacheMigration.php
- This migration executes as part of the
oro:migration:load --force command
- It runs the
oro:entity-config:cache:warmup command within a migration context
- Failure here blocks the entire migration sequence
Recommended Solutions
Short-term (Defensive)
Add exception handling in classes that query is_global field:
OrganizationProHelper.php:
public function getGlobalOrganization(): ?Organization
{
if (false === $this->globalOrganization) {
try {
$this->globalOrganization = $this->doctrine->getRepository(Organization::class)
->createQueryBuilder('org')
->select('org')
->where('org.is_global = :isGlobal')
->setParameter('isGlobal', true)
->getQuery()
->getOneOrNullResult();
} catch (QueryException $e) {
// During initialization, is_global metadata may not yet be synchronized
// Fall back to first enabled organization
$this->globalOrganization = $this->doctrine->getRepository(Organization::class)
->createQueryBuilder('org')
->select('org')
->where('org.enabled = :enabled')
->setParameter('enabled', true)
->orderBy('org.id', 'ASC')
->setMaxResults(1)
->getQuery()
->getOneOrNullResult() ?? null;
}
}
return $this->globalOrganization;
}
OwnershipProConditionDataBuilder.php:
private function getGlobalOrganizationId(?Organization $tokenOrganization): ?int
{
if (!$this->globalOrganizationId) {
try {
if ($tokenOrganization && $tokenOrganization->getIsGlobal()) {
$this->globalOrganizationId = $tokenOrganization->getid();
} else {
$globalOrganization = $this->doctrine->getRepository(Organization::class)
->findOneBy(['is_global' => true]);
if ($globalOrganization instanceof Organization) {
$this->globalOrganizationId = $globalOrganization->getid();
}
}
} catch (\Throwable $e) {
// During initialization, is_global metadata may not yet be synchronized
// Return null and try again later
return null;
}
}
return $this->globalOrganizationId;
}
Additional information
Similar Root Causes
This is a well-known pattern in ORM frameworks when dealing with dynamic/extended entity metadata:
- Entity schema updates ≠ Entity metadata updates
- Schema changes don't automatically invalidate and refresh ORM metadata caches
- Initialization order matters significantly
Impact
- Fresh Installations: Completely blocked - cannot complete installation
- Upgrade Installations: May be affected if migrations bring in OrganizationProBundle features
- Environment: Affects all PHP versions, but most visible on PHP 8.4+ with strict type checking
Workaround
For now, users can:
- Skip the affected bundles during initial migrations
- Run two-step installation (migrations, then warmup separately)
- Apply defensive exception handling in application code
Verification Commands
Before fix (will fail during migrations):
# This will fail during the WarmUpEntityConfigCacheMigration step
bin/console oro:migration:load --force 2>&1 | grep -A 10 "is_global"
Direct warmup (also fails during initialization):
# This will fail if entity metadata not yet synchronized
bin/console oro:entity-config:cache:warmup -vvv 2>&1 | grep -A 10 "is_global"
After fix:
# Both should complete successfully
bin/console oro:migration:load --force
bin/console oro:entity-config:cache:warmup
bin/console oro:platform:update --force
Related Issues
This issue is related to the broader extended entity initialization sequence. Similar problems may exist with:
- Other extended fields accessed during initialization
- Custom extended entities added by bundles
- Entity config loading before extended metadata is ready
Environment Notes
- Oro Platform 6.1.0 is on PHP 8.4.14+
Summary
During fresh Oro Platform installation (specifically when running
bin/console oro:migration:load --forceorbin/console oro:platform:update --force), the initialization process fails with a DoctrineQueryExceptionwhen the entity config cache warmup step tries to query theOrganization.is_globalfield. The field should have been added by theOrganizationProBundleinstaller, but Doctrine's extended entity metadata has not been synchronized yet, causing "field doesn't exist" semantic errors.This is a classic initialization order race condition affecting fresh installations on PHP 8.4+ where strict type checking is enforced.
Steps to reproduce
var/installedmarker exists to skip the web installer:Why This Step Triggers the Bug:
The
oro:migration:loadcommand executes all pending migrations. One of these migrations isWarmUpEntityConfigCacheMigrationfromEntityConfigBundle, which internally runs theoro:entity-config:cache:warmupcommand. This is a migration query, not a separate step. The error occurs during the migration sequence.Actual Result
During step 5, the migration sequence fails at the
WarmUpEntityConfigCacheMigrationwith:The entire migration sequence stops, blocking the installation. No further migrations run after this failure.
Expected Result
The platform initialization should complete successfully even on fresh installations. The extended entity field
is_globalshould either:A fresh installation should not fail due to uninitialized extended entity metadata.
Details about your environment
Root Cause Analysis
The Initialization Sequence Problem
Migration starts:
oro:migration:loadcommand executesOrganizationProBundle installer runs (via
OroOrganizationProBundleInstaller.php):is_globalcolumn tooro_organizationtable (lines 48-64)Entity config cache warmup runs (via
WarmUpEntityConfigCacheMigration):oro:entity-config:cache:warmupcommandis_globalfield:OrganizationProHelper::getGlobalOrganization()at line 54OwnershipProConditionDataBuilder::getGlobalOrganizationId()at line 110Doctrine metadata mismatch:
is_globalfieldWhy This Happens
The extended entity metadata synchronization happens after the entity config cache is warmed up, but the code tries to query the field during warmup. This creates a race condition where:
Affected Code Files
Primary Locations (Query Failures):
vendor/oro/platform-enterprise/src/Oro/Bundle/OrganizationProBundle/Helper/OrganizationProHelper.php(line 54)vendor/oro/platform-enterprise/src/Oro/Bundle/SecurityProBundle/ORM/Walker/OwnershipProConditionDataBuilder.php(line 110)Extended Entity Definition:
vendor/oro/platform-enterprise/src/Oro/Bundle/OrganizationProBundle/Migrations/Schema/OroOrganizationProBundleInstaller.php(lines 48-64)Triggered By:
vendor/oro/platform/src/Oro/Bundle/EntityConfigBundle/Migration/WarmUpEntityConfigCacheMigration.phporo:migration:load --forcecommandoro:entity-config:cache:warmupcommand within a migration contextRecommended Solutions
Short-term (Defensive)
Add exception handling in classes that query
is_globalfield:OrganizationProHelper.php:
OwnershipProConditionDataBuilder.php:
Additional information
Similar Root Causes
This is a well-known pattern in ORM frameworks when dealing with dynamic/extended entity metadata:
Impact
Workaround
For now, users can:
Verification Commands
Before fix (will fail during migrations):
Direct warmup (also fails during initialization):
After fix:
# Both should complete successfully bin/console oro:migration:load --force bin/console oro:entity-config:cache:warmup bin/console oro:platform:update --forceRelated Issues
This issue is related to the broader extended entity initialization sequence. Similar problems may exist with:
Environment Notes