Activiti/Activiti · error · IllegalArgumentException
cronExpression cannot be null
Error message
cronExpression cannot be null
What it means
The CronExpression(String, ClockReader) constructor explicitly rejects a null cron expression string with IllegalArgumentException('cronExpression cannot be null'). This is a fail-fast contract check before any parsing happens. Any scheduler setup that passes a null expression hits this immediately.
Solutions
- Ensure the timer timeCycle/duedateDescription value is non-null before constructing the calendar or CronExpression.
- Add a null/blank check with a clear error at the configuration-loading layer.
- Fix the source of the null: missing BPMN timeCycle element, unset process variable, or missing config entry.
- Provide a default schedule expression when configuration is absent, if a fallback is acceptable.
Example fix
// before
CronExpression ce = new CronExpression(cfg.getString("timer.cron"), clockReader); // may be null
// after
String cron = cfg.getString("timer.cron");
if (cron == null || cron.trim().isEmpty()) throw new IllegalStateException("timer.cron must be set");
CronExpression ce = new CronExpression(cron, clockReader); Defensive patterns
Strategy: validation
Validate before calling
Objects.requireNonNull(cronExpression, "cronExpression cannot be null");
if (cronExpression.trim().isEmpty()) throw new IllegalArgumentException("cronExpression cannot be empty"); Type guard
boolean hasCron(TimerDefinition def) { return def != null && def.getTimeCycle() != null && !def.getTimeCycle().trim().isEmpty(); } Try / catch
try {
return new CronExpression(expr, clockReader);
} catch (IllegalArgumentException | ParseException e) {
throw new IllegalArgumentException("timer cron not configured/valid: " + e.getMessage(), e);
} Prevention
- Default missing timer config explicitly at load time rather than letting null flow through.
- Assert non-null timeCycle in BPMN model validation at deployment.
- Fail fast in configuration parsing, not deep in the scheduler.
- Log which timer/process element had the missing expression.
When it happens
Trigger: Calling `new CronExpression(null, clockReader)` (or the two-arg variant used by AdvancedSchedulerResolverWithTimeZone at CronExpression.java:246) when the duedateDescription/timeCycle value resolved from process configuration or variables is null.
Common situations: BPMN timer with a missing or empty timeCycle element yielding null; a process variable feeding the timer expression not set at runtime; configuration key renamed/removed so the lookup returns null; deserialized timer definitions losing the expression field.
Related errors
- Cannot parse duration
- Failed to parse scheduler expression
- Illegal cron expression format
- Unexpected end of expression.
- businessCalendars can not be null
AI-assisted analysis of Activiti/Activiti@56435b1a97 (2026-09-09).
Data as JSON: /api/errors/c364fefa7d8a7537.
Report an issue: GitHub.
Appendix: source
Thrown at activiti-core/activiti-engine/src/main/java/org/activiti/engine/impl/calendar/CronExpression.java:246
* @throws java.text.ParseException
* if the string expression cannot be parsed into a valid <CODE>CronExpression</CODE>
*/
public CronExpression(String cronExpression, ClockReader clockReader, TimeZone timeZone) throws ParseException {
this(cronExpression, clockReader);
this.timeZone = timeZone;
}
/**
* Constructs a new <CODE>CronExpression</CODE> based on the specified parameter.
*
* @param cronExpression
* String representation of the cron expression the new object should represent
* @throws java.text.ParseException
* if the string expression cannot be parsed into a valid <CODE>CronExpression</CODE>
*/
public CronExpression(String cronExpression, ClockReader clockReader) throws ParseException {
if (cronExpression == null) {
throw new IllegalArgumentException("cronExpression cannot be null");
}
this.clockReader = clockReader;
this.cronExpression = cronExpression.toUpperCase(Locale.US);
buildExpression(this.cronExpression);
}
/**
* Returns the time zone for which this <code>CronExpression</code> will be resolved.
*/
public TimeZone getTimeZone() {
if (timeZone == null) {
timeZone = clockReader.getCurrentTimeZone();
}
return timeZone;
}View on GitHub (pinned to 56435b1a97)