I created a whitelist to allow the QuartzGateway to run. Now I am getting errors. AI produced this.
The error at line 64 of overview.cfm is a symptom of two chained failures:
Immediate Error:
overview.cfm:64
attempts to evaluate . However, hasStorage is only set if
Action.cfc:overview()
succeeds. Because an exception occurred during overview(), hasStorage was never initialized, causing Lucee to throw:
text
variable [HASSTORAGE] doesn’t exist
Root Cause (The Underlying Exception): In application.log and gateway.log, overview() failed because sendGatewayMessage(“quartz-task”, …) threw:
text
Component [org.lucee.extension.quartz.QuartzGateway] has no accessible Member with name [CONFIGFILE]
In Lucee’s Event Gateway architecture (CFCGateway.java / GatewayEngineImpl.java), Lucee does not maintain a single persistent CFC instance across calls. Every invocation (init, start, getState, sendMessage) creates a new QuartzGateway.cfc instance. Because variables.configFile was only set inside init(), subsequent calls to start() and sendMessage() on new instances find variables.configFile undefined.
Deep-Dive Analysis
- The Immediate Failure: overview.cfm:64
In
QuartzStore/Action.cfc
:
cfm
public function overview(struct lang, struct app, struct req) {
try {
variables.state = GatewayState(variables.gatewayName);
variables.storage = sendGatewayMessage(variables.gatewayName, {
“action”: “store”
,“type”: “raw”
});
variables.storageLoaded = deserializeJSON(variables.storage);
variables.hasStorage = structCount(storageLoaded) > 0;
}
catch(cfcatch) {
handleException(lang, app, req, cfcatch);
}
}
When sendGatewayMessage fails:
variables.hasStorage is never set.
handleException logs the error and stores the exception in session[“expectionQuartzStore”].
The controller proceeds to render
overview.cfm
:
cfm
64:
65:
Modify your Storage
…
68: <cfif structKeyExists(session,exceptionKey)>
69:
…
100:
Because line 64 references hasStorage directly without a default or structKeyExists, it fails before it can even evaluate the or reach the block.
- The Underlying Root Cause: QuartzGateway.cfc
From D:\Jetty-Bases\Jetty-Base-12\lucee-server\context\logs\application.log:
text
“ERROR”,“qtp1660794022-190”,“09/08/2026”,“23:19:49”,“https://local.caminha.me:443”,“webadmin7.1.0.204”,
“Component [org.lucee.extension.quartz.QuartzGateway] has no accessible Member with name [CONFIGFILE]
at org.lucee.extension.quartz.quartzgateway_cfc$cf.udfCall(/org/lucee/extension/quartz/QuartzGateway.cfc:124)
at lucee.runtime.functions.gateway.SendGatewayMessage.call(SendGatewayMessage.java:36)
at quartzstore.action_cfc$cf.udfCall(/lucee_plugin_directory/QuartzStore/Action.cfc:55)”
And in gateway.log:
text
“ERROR”,“EventGateway-quartz-task”,“09/08/2026”,“23:19:37”,“https://local.caminha.me:443”,“Gateway:quartz-task”,
“Component [org.lucee.extension.quartz.QuartzGateway] has no accessible Member with name [CONFIGFILE]”
Looking at
QuartzGateway.cfc
:
cfm
public void function init(string id, struct config, component listener) {
var path = server.system.environment.QUARTZ_CONFIGFILE ?: “”;
if (isEmpty(path)) {
path = config.custom.configFile ?: “{lucee-server}/quartz/config.json”;
path = expandPath(path);
}
variables.configFile = path;
…
}
public void function start() {
variables.instance = new Quartz(variables.configFile); // ← Fails here if init() was on another instance
variables.instance.start();
}
public string function sendMessage(struct data) {
if (!isNull(variables.instance))
return variables.instance.sendMessageInstance(data);
else {
return Quartz::sendMessageStatic(variables.configFile, data); // ← Fails here at line 124
}
}
Why variables.configFile does not exist:
In Lucee’s event gateway implementation (lucee.runtime.gateway.GatewayEngineImpl):
engine.call and engine.callOneWay call getCFC(pc, uri), which instantiates a new instance of QuartzGateway.cfc for each operation in a temporary PageContext.
When the gateway is initialized, init(…) is called on Instance #1, setting variables.configFile on Instance #1.
When the gateway starts (EventGateway-quartz-task), start() is invoked on Instance #2. Instance #2 has an empty variables scope, so variables.configFile is undefined. start() throws an error and the gateway remains stopped.
When the admin page runs sendGatewayMessage, Instance #3 is created. Because the gateway is stopped, sendMessage executes Quartz::sendMessageStatic(variables.configFile, data). Again, Instance #3 has an empty variables scope, throwing Component [org.lucee.extension.quartz.QuartzGateway] has no accessible Member with name [CONFIGFILE].
Recommended Remediation Plan
To make the Quartz extension robust and prevent these failures:
- Fix
QuartzGateway.cfc
Persist state in static scope: In Lucee, static variables persist across CFC instantiations. Storing static.configFile and static.instance ensures that start(), stop(), getState(), and sendMessage() share the configuration and the running Quartz scheduler instance.
Self-Healing getConfigFile(): Add a fallback helper that returns static.configFile if available, or resolves server.system.environment.QUARTZ_CONFIGFILE ?: expandPath(“{lucee-server}/quartz/config.json”) and creates the default directory and config file if it does not already exist.
cfm
component {
static {
static.DEFAULT_CONFIG = ‘…’;
static.instance = nullValue();
static.configFile = “”;
static.config = {};
static.id = “”;
}
private string function getConfigFile(struct config = {}) {
if (len(static.configFile) && fileExists(static.configFile)) {
return static.configFile;
}
var path = server.system.environment.QUARTZ_CONFIGFILE ?: “”;
if (isEmpty(path)) {
path = arguments.config.custom.configFile ?: (static.config.custom.configFile ?: “{lucee-server}/quartz/config.json”);
path = expandPath(path);
}
static.configFile = path;
ensureConfigFileExists(path);
return path;
}
…
2. Defensive Coding in
QuartzStore/Action.cfc
Pre-initialize variables.hasStorage = false;, variables.storage = “”;, and variables.storageLoaded = {}; at the top of overview(). If sendGatewayMessage fails, hasStorage is cleanly false rather than undefined.
3. Defensive Coding in
QuartzStore/overview.cfm
Change to <cfif hasStorage ?: false> so that an unhandled error does not crash the page template.
Render the session error banner above the block so the admin user sees the error message when a gateway failure occurs.