microsoft/qlib · error · ValueError
Unsupported earlystopping mode: {mode}
Error message
Unsupported earlystopping mode: {mode} What it means
ValueError from `EarlyStopping.__init__` (qlib/rl/trainer/callbacks.py:112). The `mode` argument controls whether training stops when the monitored metric stops decreasing (`min`) or increasing (`max`); anything other than the exact strings 'min' or 'max' is rejected before any training starts.
Source
Thrown at qlib/rl/trainer/callbacks.py:112
self,
monitor: str = "reward",
min_delta: float = 0.0,
patience: int = 0,
mode: Literal["min", "max"] = "max",
baseline: float | None = None,
restore_best_weights: bool = False,
):
super().__init__()
self.monitor = monitor
self.patience = patience
self.baseline = baseline
self.min_delta = abs(min_delta)
self.restore_best_weights = restore_best_weights
self.best_weights: Any | None = None
if mode not in ["min", "max"]:
raise ValueError("Unsupported earlystopping mode: " + mode)
if mode == "min":
self.monitor_op = np.less
elif mode == "max":
self.monitor_op = np.greater
if self.monitor_op == np.greater:
self.min_delta *= 1
else:
self.min_delta *= -1
def state_dict(self) -> dict:
return {"wait": self.wait, "best": self.best, "best_weights": self.best_weights, "best_iter": self.best_iter}
def load_state_dict(self, state_dict: dict) -> None:
self.wait = state_dict["wait"]
self.best = state_dict["best"]
self.best_weights = state_dict["best_weights"]View on GitHub (pinned to 79633dd950)
Solutions
- Set `mode` to exactly `"min"` (loss, PAW error) or `"max"` (return, reward) when constructing the callback.
- If migrating a Keras config with `mode: auto`, resolve it yourself: pick 'min' when monitor name contains 'loss' or 'err', else 'max'.
- Lowercase/validate user-supplied mode before passing: `mode = mode.lower(); assert mode in ("min", "max")`.
Example fix
// before cb = EarlyStopping(monitor="val_loss", patience=5, mode="auto") // Keras-style, rejected // after cb = EarlyStopping(monitor="val_loss", patience=5, mode="min")
Defensive patterns
Strategy: validation
Validate before calling
mode = (mode or "").lower()
assert mode in ("min", "max"), f"mode must be 'min' or 'max', got {mode!r}" Type guard
def is_earlystopping_mode(mode) -> bool:
return isinstance(mode, str) and mode in ("min", "max") Try / catch
try:
cb = EarlyStopping(monitor=m, patience=p, mode=mode)
except ValueError as e:
if "Unsupported earlystopping mode" in str(e):
mode = "min" if ("loss" in m or "err" in m) else "max"
cb = EarlyStopping(monitor=m, patience=p, mode=mode)
else:
raise Prevention
- Resolve Keras-style 'auto' mode to min/max yourself before constructing the callback.
- Lowercase and validate mode in config loaders.
- Remember mode is case-sensitive here, unlike some other frameworks.
When it happens
Trigger: Passing `mode="MIN"` (case-sensitive), `mode="auto"` (supported by Keras but not here), `mode=0`, or None to the EarlyStopping callback constructor.
Common situations: Porting Keras/PyTorch Lightning early-stopping configs to qlib where `auto` mode or uppercase modes are accepted; YAML configs with a typo; default-None configs that assume the callback fills in a mode.
Related errors
- unknown metric `%s`
- unknown metric `%s`
- unknown metric `%s`
- file "{}" does not exist
- Only py/yml/yaml/json type are supported now!
AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15).
Data as JSON: /api/errors/1d56b9e16802b1ee.
Report an issue: GitHub.