OpenBMB/ChatDev · error · ConfigError

max_iterations must be an integer

Error message

max_iterations must be an integer

What it means

LoopCounterConfig.from_dict could not coerce the 'max_iterations' value (default 10) to int. Strings like 'ten', None, or lists raise TypeError/ValueError in int() and are reported as a config error.

Source

Thrown at entity/configs/node/loop_counter.py:31

)


@dataclass
class LoopCounterConfig(BaseConfig):
    """Configuration schema for the loop counter node type."""

    max_iterations: int = 10
    reset_on_emit: bool = True
    message: Optional[str] = None

    @classmethod
    def from_dict(cls, data: Mapping[str, Any] | None, *, path: str) -> "LoopCounterConfig":
        mapping = require_mapping(data or {}, path)
        max_iterations_raw = mapping.get("max_iterations", 10)
        try:
            max_iterations = int(max_iterations_raw)
        except (TypeError, ValueError) as exc:  # pragma: no cover - defensive
            raise ConfigError(
                "max_iterations must be an integer",
                extend_path(path, "max_iterations"),
            ) from exc

        if max_iterations < 1:
            raise ConfigError("max_iterations must be >= 1", extend_path(path, "max_iterations"))

        reset_on_emit = bool(mapping.get("reset_on_emit", True))
        message = optional_str(mapping, "message", path)

        return cls(
            max_iterations=max_iterations,
            reset_on_emit=reset_on_emit,
            message=message,
            path=path,
        )

    def validate(self) -> None:

View on GitHub (pinned to 4fb2db0ea9)

Solutions

  1. Set max_iterations to an integer, e.g. 10
  2. Use a numeric string only if unavoidable ('5' works, but prefer int)
  3. If sourcing from env, wrap: int(os.environ.get('MAX_ITER', '10')) with try/except and a clear message

Example fix

# before
{"max_iterations": "ten"}
# after
{"max_iterations": 10}
Defensive patterns

Strategy: validation

Validate before calling

raw = data.get('max_iterations', 10)
try:
    data['max_iterations'] = int(raw)
except (TypeError, ValueError):
    data['max_iterations'] = 10

Type guard

def coercion_safe(data: dict) -> bool:
    try:
        int(data.get('max_iterations', 10))
        return True
    except (TypeError, ValueError):
        return False

Try / catch

try:
    LoopCounterConfig.from_dict(data, path='lc')
except ConfigError as e:
    if 'max_iterations' in e.path:
        data['max_iterations'] = 10
        LoopCounterConfig.from_dict(data, path='lc')
    else:
        raise

Prevention

When it happens

Trigger: Passing max_iterations as a non-numeric string, null, or a list/dict. Note numeric strings like '5' DO parse because int() accepts them, so only truly non-numeric values fail.

Common situations: YAML value left blank (null); env-var injection of an empty string; prose values pasted instead of numbers.

Related errors


AI-assisted analysis of OpenBMB/ChatDev@4fb2db0ea9 (2026-08-27). Data as JSON: /api/errors/bc7537fad56f4238. Report an issue: GitHub.