flowable/flowable-engine · error · FlowableIllegalArgumentException

Converter can only convert string to localDateTime

Error message

Converter can only convert string to localDateTime

What it means

LocalDateTimeRestVariableConverter.getVariableValue deserializes a REST variable into a java.time.LocalDateTime and requires the REST value to be a String. A non-String value fails the instanceof guard and throws FlowableIllegalArgumentException, because only strings can be passed to LocalDateTime.parse.

Source

Thrown at modules/flowable-common-rest/src/main/java/org/flowable/common/rest/variable/LocalDateTimeRestVariableConverter.java:39

 * @author Filip Hrisafov
 */
public class LocalDateTimeRestVariableConverter implements RestVariableConverter {

    @Override
    public String getRestTypeName() {
        return "localDateTime";
    }

    @Override
    public Class<?> getVariableType() {
        return LocalDateTime.class;
    }

    @Override
    public Object getVariableValue(EngineRestVariable result) {
        if (result.getValue() != null) {
            if (!(result.getValue() instanceof String)) {
                throw new FlowableIllegalArgumentException("Converter can only convert string to localDateTime");
            }
            try {
                return LocalDateTime.parse((String) result.getValue());
            } catch (DateTimeParseException e) {
                throw new FlowableIllegalArgumentException("The given variable value is not a localDateTime: '" + result.getValue() + "'", e);
            }
        }
        return null;
    }

    @Override
    public void convertVariableValue(Object variableValue, EngineRestVariable result) {
        if (variableValue != null) {
            if (!(variableValue instanceof LocalDateTime)) {
                throw new FlowableIllegalArgumentException("Converter can only convert localDateTime");
            }
            result.setValue(variableValue.toString());
        } else {

View on GitHub (pinned to d6d39ce1c6)

Solutions

  1. Send the value as an ISO-8601 local datetime string (yyyy-MM-dd'T'HH:mm:ss), e.g. "2026-09-10T14:30:00".
  2. Ensure the client's JSON serializer emits dates as ISO strings, not timestamps or arrays.
  3. Convert epoch millis/Instant values to LocalDateTime strings client-side.
  4. If the payload carries an offset/zone, either strip it or use a variable type that supports it.

Example fix

// before
{ "type": "localDateTime", "value": [2026, 9, 10, 14, 30] }

// after
{ "type": "localDateTime", "value": "2026-09-10T14:30:00" }
Defensive patterns

Strategy: validation

Validate before calling

if (!(rawValue instanceof String s)) {
    throw new IllegalArgumentException("localDateTime variable must be a JSON string, got: "
        + (rawValue == null ? "null" : rawValue.getClass().getSimpleName()));
}
LocalDateTime.parse(s); // fail fast on format

Type guard

static boolean isIsoLocalDateTimeString(Object v) {
    return v instanceof String s && s.matches("\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}(:\\d{2}(\\.\\d+)?)?");
}

Try / catch

try {
    Object value = converter.getVariableValue(restVar);
} catch (FlowableIllegalArgumentException e) {
    log.error("Invalid localDateTime variable: {}", restVar.getValue(), e);
}

Prevention

When it happens

Trigger: Sending a localDateTime REST variable whose JSON value is a number (epoch), array (Jackson date-as-array), object, or boolean instead of an ISO-8601 datetime string, so result.getValue() is not a String.

Common situations: Clients serializing datetimes as epoch millis or [yyyy,MM,dd,...] arrays; typed HTTP clients deserializing into OffsetDateTime/Instant before the converter runs; timezone-aware payloads sent to a timezone-less variable type.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/be1d6f1ed7de4aeb. Report an issue: GitHub.