Found during a Strict review of ConductionNL/keepiq#712. Present on ConductionNL/.github@main (hydra-gates/scripts/lib/check_apphost_autoload_prelude.py, last changed in 52146a9).
Impact
Gate-64 (apphost-autoload-prelude) only passes an AppHost app whose prelude calls registerAutoloading(...) naming openregister. In practice that means \OC_App::registerAutoloading(). Nextcloud 35 removed that method. On NC 35, an app that satisfies the gate breaks. Its prelude throws, the catch (\Throwable) returns false, the class_exists(Bootstrap::class) guard skips the AppHost wiring, and /api/health plus /api/metrics return 500 with an HTML page. Nothing is logged.
It fires on the happy path, on a healthy instance with OpenRegister enabled. The only precondition is an app id that sorts before openregister, because only those apps depend on the prelude for load order. An app that fixes itself with public API has to add an apphost-prelude exclude to get past the gate, as keepiq#712 now does.
The chain
nextcloud/server@stable34 lib/private/legacy/OC_App.php:104: registerAutoloading() exists (@internal).
nextcloud/server@stable35: OC_App has no registerAutoloading(). The method moved to OC\App\AppManager::registerAutoloading() at line 595, which is private too and not on OCP\App\IAppManager.
check_apphost_autoload_prelude.py:96: PRELUDE = re.compile(r"registerAutoloading\s*\(([^)]*)\)", re.S). The accepted alternative is loadApp('openregister') (line 115), which boots OpenRegister before its own register(), and keepiq#712 explains why that is worse.
- keepiq#712 replaced the call with
spl_autoload_register over IAppManager::getAppPath('openregister') . '/lib/', which is public API. It had to suppress gate-64 at lib/AppInfo/Application.php:138. The comment there says "Tracked for hydra-gates", but no issue existed until this one.
Verified by reading code at ConductionNL/.github@main and ConductionNL/keepiq@7f8e256. Not executed on NC 35 here; keepiq#712's Newman run on stable35 is the reproduction.
Apps that still call the removed method on development
Only the apps that sort before openregister depend on the prelude:
| App |
max-version on development |
NC 35 exposure |
| integriq |
35 |
Live: advertises NC 35 while still calling \OC_App::registerAutoloading() (lib/AppInfo/Application.php:210) |
| buildiq, decidiq, dossiq, filinq, hermiq, larpinq, learniq |
34 |
Breaks on the bump to 35 |
| keepiq |
34 → 35 in #712 |
Fixed in #712 with a suppression |
pipelinq, planninq and thematiq also call it but sort after openregister, so they do not depend on it for load order. They still throw into their catch on NC 35.
Close condition
- Gate-64 accepts a prelude that registers the
OCA\OpenRegister\ PSR-4 prefix by public means: spl_autoload_register plus IAppManager::getAppPath('openregister'), or an equivalent the gate can recognise. It also stops requiring registerAutoloading, or at least stops requiring it on apps that declare max-version >= 35.
- A gate fixture covers the keepiq#712 shape passing without an exclude.
- keepiq's
apphost-prelude exclude can then be removed. A follow-up per app in the table above ports its prelude, integriq first.
Found during a Strict review of ConductionNL/keepiq#712. Present on
ConductionNL/.github@main(hydra-gates/scripts/lib/check_apphost_autoload_prelude.py, last changed in 52146a9).Impact
Gate-64 (
apphost-autoload-prelude) only passes an AppHost app whose prelude callsregisterAutoloading(...)namingopenregister. In practice that means\OC_App::registerAutoloading(). Nextcloud 35 removed that method. On NC 35, an app that satisfies the gate breaks. Its prelude throws, thecatch (\Throwable)returns false, theclass_exists(Bootstrap::class)guard skips the AppHost wiring, and/api/healthplus/api/metricsreturn 500 with an HTML page. Nothing is logged.It fires on the happy path, on a healthy instance with OpenRegister enabled. The only precondition is an app id that sorts before
openregister, because only those apps depend on the prelude for load order. An app that fixes itself with public API has to add anapphost-prelude excludeto get past the gate, as keepiq#712 now does.The chain
nextcloud/server@stable34lib/private/legacy/OC_App.php:104:registerAutoloading()exists (@internal).nextcloud/server@stable35:OC_Apphas noregisterAutoloading(). The method moved toOC\App\AppManager::registerAutoloading()at line 595, which is private too and not onOCP\App\IAppManager.check_apphost_autoload_prelude.py:96:PRELUDE = re.compile(r"registerAutoloading\s*\(([^)]*)\)", re.S). The accepted alternative isloadApp('openregister')(line 115), which boots OpenRegister before its ownregister(), and keepiq#712 explains why that is worse.spl_autoload_registeroverIAppManager::getAppPath('openregister') . '/lib/', which is public API. It had to suppress gate-64 atlib/AppInfo/Application.php:138. The comment there says "Tracked for hydra-gates", but no issue existed until this one.Verified by reading code at
ConductionNL/.github@mainandConductionNL/keepiq@7f8e256. Not executed on NC 35 here; keepiq#712's Newman run on stable35 is the reproduction.Apps that still call the removed method on
developmentOnly the apps that sort before
openregisterdepend on the prelude:max-versionon development\OC_App::registerAutoloading()(lib/AppInfo/Application.php:210)pipelinq, planninq and thematiq also call it but sort after
openregister, so they do not depend on it for load order. They still throw into their catch on NC 35.Close condition
OCA\OpenRegister\PSR-4 prefix by public means:spl_autoload_registerplusIAppManager::getAppPath('openregister'), or an equivalent the gate can recognise. It also stops requiringregisterAutoloading, or at least stops requiring it on apps that declaremax-version >= 35.apphost-prelude excludecan then be removed. A follow-up per app in the table above ports its prelude, integriq first.