kestra-io/kestra · error · PebbleException

The 'hourOfDay()' function could not parse 'date': {e2.getMe

Error message

The 'hourOfDay()' function could not parse 'date': {e2.getMessage()}

What it means

Thrown by 'hourOfDay()' when the date string cannot be parsed as either a ZonedDateTime (first attempt) or a LocalDateTime (second attempt). Both DateTimeParseException failures are caught; the second's message is wrapped into the PebbleException. This means the value was non-null but not a recognizable ISO 8601 datetime.

Source

Thrown at core/src/main/java/io/kestra/core/runners/pebble/functions/HourOfDayFunction.java:48

    public static final String NAME = "hourOfDay";

    @Override
    public Object execute(Map<String, Object> args, PebbleTemplate self, EvaluationContext context, int lineNumber) {
        Object dateArg = args.get("date");

        if (dateArg == null) {
            throw new PebbleException(null, "The 'hourOfDay()' function expects a 'date' argument.", lineNumber, self.getName());
        }

        String dateStr = dateArg.toString();

        try {
            return ZonedDateTime.parse(dateStr).getHour();
        } catch (DateTimeParseException e1) {
            try {
                return LocalDateTime.parse(dateStr).getHour();
            } catch (DateTimeParseException e2) {
                throw new PebbleException(e2, "The 'hourOfDay()' function could not parse 'date': " + e2.getMessage(), lineNumber, self.getName());
            }
        }
    }

    @Override
    public List<String> getArgumentNames() {
        return List.of("date");
    }

    @Override
    // HashMap is required here because Map.of() does not allow null values,
    // and null defaults indicate arguments with no meaningful autocompletion default.
    public Map<String, String> getArgumentDefaults() {
        HashMap<String, String> defaults = new HashMap<>();
        defaults.put("date", null);
        return defaults;
    }
}

View on GitHub (pinned to 823fada927)

Solutions

  1. Provide a full ISO 8601 datetime string with an offset for best results: hourOfDay('2026-08-14T15:30:00+02:00').
  2. Pre-format the date into ISO 8601 before the call using a task or expression.
  3. If you only have a date, append a time component (e.g. T00:00:00) so LocalDateTime.parse succeeds.
  4. Avoid locale/epoch formats; convert them upstream.

Example fix

# before - non-ISO format
h: "{{ hourOfDay('14/08/2026 15:30') }}"
# after - ISO 8601
h: "{{ hourOfDay('2026-08-14T15:30:00Z') }}"
Defensive patterns

Strategy: validation

Validate before calling

# Light ISO 8601 pre-check before calling hourOfDay().
# {{ (dateValue matches '^\\d{4}-\\d{2}-\\d{2}T.*') ? hourOfDay(dateValue) : hourOfDay(dateValue ~ 'T00:00:00') }}

Try / catch

# Pebble has no try/catch. In a wrapper task, catch DateTimeParseException and return a sentinel (e.g. -1) or log the bad input.

Prevention

When it happens

Trigger: Passing a date-only string ('2026-08-14'), a time-only string ('15:30:00'), a locale-formatted date ('14/08/2026'), an epoch number as a string, or any non-ISO 8601 textual date.

Common situations: Using a date format from another system without converting to ISO 8601; passing a date-only when a datetime is required; locale-specific formats (DD/MM/YYYY vs MM/DD/YYYY); passing a timestamp/epoch.

Related errors


AI-assisted analysis of kestra-io/kestra@823fada927 (2026-08-14). Data as JSON: /api/errors/d21d50b7c738abc5. Report an issue: GitHub.