alibaba/COLA · error · JobException

Unexpected value '${value}'

Error message

Unexpected value '${value}'

What it means

ExecutionStatus.fromValue(String) iterates all enum constants and throws JobException 'Unexpected value' when no constant name equals the input. It is a strict string-to-enum converter for persisted execution status values.

Source

Thrown at cola-components/cola-component-job/src/main/java/com/alibaba/cola/job/model/ExecutionStatus.java:29

    COMPLETED,
    FAILED,
    RUNNING,
    ROLLBACK_STARTED,
    ROLLBACK_COMPLETED,
    ROLLBACK_FAILED,
    UNKNOWN;

    public final static List<ExecutionStatus> ROLLBACK_STATUS = List.of(ROLLBACK_STARTED, ROLLBACK_FAILED,
            ROLLBACK_COMPLETED);

    @JsonCreator
    public static ExecutionStatus fromValue(String value) {
        for (ExecutionStatus s : ExecutionStatus.values()) {
            if (s.name().equals(value)) {
                return s;
            }
        }
        throw new JobException("Unexpected value '" + value + "'");
    }

    public static boolean isRollback(ExecutionStatus executionStatus) {
        return executionStatus != null && ROLLBACK_STATUS.contains(executionStatus);
    }

    public static boolean isTerminated(ExecutionStatus executionStatus) {
        return executionStatus == ExecutionStatus.COMPLETED
                || executionStatus == ExecutionStatus.FAILED
                || isRollback(executionStatus);
    }
}

View on GitHub (pinned to 352e1a8675)

Solutions

  1. Pass the exact enum constant name, e.g. ExecutionStatus.RUNNING.name()
  2. Trim and uppercase the incoming string before conversion
  3. Migrate legacy persisted values to current enum names, or add legacy constants

Example fix

// before
ExecutionStatus s = ExecutionStatus.fromValue(status.trim().toLowerCase());
// after
ExecutionStatus s = ExecutionStatus.fromValue(status.trim().toUpperCase());
Defensive patterns

Strategy: validation

Validate before calling

String v = raw == null ? null : raw.trim();
boolean known = Arrays.stream(ExecutionStatus.values()).anyMatch(s -> s.name().equals(v));
if (!known) throw new IllegalStateException("Unknown ExecutionStatus: " + raw);

Type guard

java.util.Optional<ExecutionStatus> tryFromValue(String value) {
    if (value == null) return Optional.empty();
    return Arrays.stream(ExecutionStatus.values())
        .filter(s -> s.name().equals(value.trim()))
        .findFirst();
}

Try / catch

try {
    status = ExecutionStatus.fromValue(raw);
} catch (JobException e) {
    if (e.getMessage().startsWith("Unexpected value")) {
        log.error("Persisted status '{}' is not a valid ExecutionStatus", raw, e);
        status = ExecutionStatus.FAILED; // or rethrow per policy
    } else throw e;
}

Prevention

When it happens

Trigger: Calling ExecutionStatus.fromValue with a string that is not the exact name() of an enum constant (case-sensitive, no trimming).

Common situations: Loading status values persisted by an older version whose enum names changed; passing lowercase 'running' instead of 'RUNNING'; whitespace from DB columns or message payloads.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of alibaba/COLA@352e1a8675 (2026-09-08). Data as JSON: /api/errors/46a1abc75e48db0f. Report an issue: GitHub.