NPE in `ConfigImpl` on clean boot when Event Gateways auto-start before `Component.cfc` is deployed

Following up on the warmup thread (docker-build-warmup-behaviour/17547) and LDEV-6472, there is a separate related issue on clean startup when extensions install automatic event gateways (e.g. Quartz Scheduler).

Disclaimer: I used AI to assist in this debugging/report

During initial context initialization, Lucee throws a NullPointerException:

ERROR [server.gateway] Cannot invoke "lucee.commons.io.res.Resource.getCanonicalPath()" because "a" is null
lucee.runtime.exp.NativeException: Cannot invoke "lucee.commons.io.res.Resource.getCanonicalPath()" because "a" is null
	at lucee.runtime.config.ConfigImpl.getBaseComponentPageSource(ConfigImpl.java:2296)
	at lucee.runtime.config.ConfigWebImpl.getBaseComponentPageSource(ConfigWebImpl.java:464)
	at lucee.runtime.config.ConfigWebHelper.getBaseComponentPage(ConfigWebHelper.java:254)
	at lucee.runtime.config.ConfigWebHelper.getBaseComponentInstance(ConfigWebHelper.java:277)
	at lucee.runtime.config.ConfigWebImpl.getBaseComponentInstance(ConfigWebImpl.java:1614)
	at lucee.runtime.ComponentImpl.init(ComponentImpl.java:480)
	at org.lucee.extension.quartz.quartzgateway_cfc$cf.initComponent(/org/lucee/extension/quartz/QuartzGateway.cfc)
	at org.lucee.extension.quartz.quartzgateway_cfc$cf.newInstance(/org/lucee/extension/quartz/QuartzGateway.cfc:1)
	at lucee.runtime.ComponentPageImpl.call(ComponentPageImpl.java:161)
	at lucee.runtime.gateway.GatewayEngineImpl.getCFC(GatewayEngineImpl.java:440)
	at lucee.runtime.gateway.GatewayEngineImpl.autoStart(GatewayEngineImpl.java:210)
	at lucee.runtime.config.ConfigFactoryImpl.newInstanceWeb(ConfigFactoryImpl.java:229)

Root Causes

Tracing through the Lucee 7 codebase, this is caused by three compounding issues:

1. Inverted Lifecycle Order (ConfigFactoryImpl.java:345 vs 348)

345: load(config, root, false, doNew, essentialOnly); 
     // ↳ _loadExtensionBundles() downloads/installs extensions -> registers Quartz gateway
...
348: createContextFiles(configDir, config, doNew);
     // ↳ line 4030 calls ComponentFactory.deploy() -> extracts Component.cfc from core.lco
  • In load() (line 345), Lucee installs extension bundles. Extensions registering event gateways get auto-started when newInstanceWeb() executes ((GatewayEngineImpl) configWeb.getGatewayEngine()).autoStart().
  • QuartzGateway.cfc extends Component.cfc.
  • However, ComponentFactory.deploy() (which extracts base components like Component.cfc from core.lco into components/org/lucee/cfml/) is not called until createContextFiles() at line 348.
  • Because the gateway starts before core components are unpacked, the Component.cfc lookup fails.

2. Typo in ConfigImpl.java:2294-2296

When Lucee attempts to format the component lookup error message, it hits this block:

Resource a = m.getArchive();
String archive = m.getStrArchive();
if (p != null) { // <-- Bug: checks physical resource 'p' instead of archive 'a'
    archive = a.getCanonicalPath() + " (" + m.getStrArchive() + ")"; // Throws NPE because 'a' is null!
}
  • When resolving against a physical-only mapping (such as /lucee-server/ which has "primary": "physical" and "archive": ""), archive a is null.
  • The code checks if (p != null) instead of if (a != null).
  • Because p exists, it calls a.getCanonicalPath() on null, throwing the raw NullPointerException and completely masking the underlying missing component error.

3. Unnecessary Gateway Auto-Start in Warmup Mode

  • In LUCEE_ENABLE_WARMUP=true (or any headless build mode), external resources (databases, message queues, mail servers) do not exist.
  • Auto-starting event gateways during warmup is counter-productive: it spawns background threads and attempts connections against non-existent infrastructure before immediately shutting down.

Suggested Fixes

  1. Suppress Gateway Auto-Start During Warmup: When LUCEE_ENABLE_WARMUP=true, skip ((GatewayEngineImpl) configWeb.getGatewayEngine()).autoStart() in ConfigFactoryImpl.java:229. Gateways have no purpose running during a build warmup pass.
  2. Fix NPE in ConfigImpl.java:2296: Change if (p != null) to if (a != null).
  3. Ensure Core Components Deploy First: Run ComponentFactory.deploy() before _loadExtensionBundles() so base components exist whenever extensions load.

Thanks for the detailed report. Filed this as a separate bug (not LDEV-6472):

https://luceeserver.atlassian.net/browse/LDEV-6481