flowable/flowable-engine · error · FlowableIllegalArgumentException

Converter can only convert string to instant

Error message

Converter can only convert string to instant

What it means

InstantRestVariableConverter.getVariableValue parses a String into java.time.Instant using Instant.parse (ISO-8601 instant format). If the stored value is non-null but not a String, it throws this FlowableIllegalArgumentException because only strings can be parsed.

Solutions

  1. Request the variable with the REST type matching the stored value (e.g. 'date' for java.util.Date).
  2. Store the variable as an ISO-8601 instant string (e.g. 2026-09-10T00:00:00Z).
  3. Convert the value with Instant.toString() before storing if custom code populates it.
  4. Check for converter type-name collisions in the REST variable converter registry.

Example fix

// before
runtimeService.setVariable(executionId, "firedAt", new Date()); // served via instant converter
// after
runtimeService.setVariable(executionId, "firedAt", Instant.now().toString());
Defensive patterns

Strategy: type-guard

Validate before calling

public static boolean isInstantString(Object v) { return v == null || v instanceof String; }

Type guard

public static boolean isString(Object v) { return v instanceof String; }

Try / catch

try {
    Object ts = restClient.getVariable(id, "firedAt");
} catch (FlowableIllegalArgumentException e) {
    if (e.getMessage().equals("Converter can only convert string to instant")) {
        // request the variable with the correct REST type or re-store as ISO string
    } else { throw e; }
}

Prevention

When it happens

Trigger: Reading a REST variable typed as 'instant' when the engine value is not a String (e.g. java.util.Date, Instant object, or number).

Common situations: Variable stored by the engine as Date but served through the instant converter; custom code setting the variable as an Instant object; type name mismatch between stored and requested REST 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/eeed8d88c64d386c. Report an issue: GitHub.

Appendix: source

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

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

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

    @Override
    public Class<?> getVariableType() {
        return Instant.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 instant");
            }
            try {
                return Instant.parse((String) result.getValue());
            } catch (DateTimeParseException e) {
                throw new FlowableIllegalArgumentException("The given variable value is not an instant: '" + result.getValue() + "'", e);
            }
        }
        return null;
    }

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

View on GitHub (pinned to d6d39ce1c6)