twentyhq/twenty · warning · Error
Cron expression is required
Error message
Cron expression is required
What it means
describeCronExpression guards its entry: it throws when `expression` is undefined/null or trims to empty, before any parsing attempt. This is input validation, distinct from the catch-all wrapper at line 114.
Source
Thrown at packages/twenty-front/src/modules/workflow/workflow-trigger/utils/cron-to-human/describeCronExpression.ts:22
import { getDayOfMonthDescription } from './descriptors/getDayOfMonthDescription';
import { getDayOfWeekDescription } from './descriptors/getDayOfWeekDescription';
import { getHoursDescription } from './descriptors/getHoursDescription';
import { getMinutesDescription } from './descriptors/getMinutesDescription';
import { getMonthsDescription } from './descriptors/getMonthsDescription';
import {
type CronDescriptionOptions,
DEFAULT_CRON_DESCRIPTION_OPTIONS,
} from './types/cronDescriptionOptions';
import { parseCronExpression } from './utils/parseCronExpression';
export const describeCronExpression = (
expression: string,
options: CronDescriptionOptions = DEFAULT_CRON_DESCRIPTION_OPTIONS,
localeCatalog?: Locale,
): string => {
if (!isDefined(expression) || expression.trim() === '') {
throw new Error('Cron expression is required');
}
try {
const parts = parseCronExpression(expression);
const mergedOptions = { ...DEFAULT_CRON_DESCRIPTION_OPTIONS, ...options };
const descriptions: string[] = [];
// Smart priority: Use hours description when we have specific hours,
// otherwise use minutes description for patterns like */5
const hoursDescription = getHoursDescription(
parts.hours,
parts.minutes,
mergedOptions,
);
const minutesDescription = getMinutesDescription(
parts.minutes,
mergedOptions,View on GitHub (pinned to 1f5dd2bbd2)
Solutions
- Check the value is a non-empty string before calling (early-return in the UI).
- Provide a sensible default cron expression (e.g., '0 * * * *') for new workflow triggers.
- Guard the call site: if (!expression) return '';
Example fix
// before: const desc = describeCronExpression(schedule ?? ''); // after: const desc = schedule ? describeCronExpression(schedule) : '';
Defensive patterns
Strategy: validation
Validate before calling
const safeDescribeCron = (expr: string | undefined | null): string => expr && expr.trim() ? describeCronExpression(expr) : '';
Type guard
const isNonEmptyCronString = (v: unknown): v is string => typeof v === 'string' && v.trim().length > 0;
Prevention
- Default new workflow trigger schedules to a concrete cron (e.g., '0 * * * *') instead of empty.
- Guard UI render of the human description with a truthy check on the schedule value.
When it happens
Trigger: Calling describeCronExpression('') , describeCronExpression(undefined as any), or with a whitespace-only string. UI rendering the cron human description before a schedule value has been set.
Common situations: Workflow trigger schedule UI rendered with an empty default. Programmatic call paths that pass through before the user picks a frequency.
Related errors
- Failed to describe cron expression: ${errorMessage}
- Cron expression is required
- Invalid cron expression. Expected 4-6 fields, got ${parts.le
- Malformed workflow version: missing steps information; be su
- Invalid cron expression: ${errorMessage}
AI-assisted analysis of twentyhq/twenty@1f5dd2bbd2 (2026-08-12).
Data as JSON: /api/errors/f130ca8fc85a5b6b.
Report an issue: GitHub.