OpenBMB/ChatDev · error · ConfigError

top_k must be a positive integer

Error message

top_k must be a positive integer

What it means

MemoryRetrieveConfig.from_dict validates that 'top_k' (default 3) is an int greater than zero. Non-int values (including floats like 3.0, bools, or strings) and values <= 0 raise this ConfigError.

Source

Thrown at entity/configs/node/memory.py:456

        stages_raw = mapping.get("retrieve_stage")
        stages: List[AgentExecFlowStage] | None = None
        if stages_raw is not None:
            stage_list = ensure_list(stages_raw)
            parsed: List[AgentExecFlowStage] = []
            for idx, item in enumerate(stage_list):
                try:
                    parsed.append(AgentExecFlowStage(item))
                except ValueError as exc:
                    raise ConfigError(
                        f"retrieve_stage entries must be one of {[stage.value for stage in AgentExecFlowStage]}",
                        extend_path(path, f"retrieve_stage[{idx}]"),
                    ) from exc
            stages = parsed

        top_k_value = mapping.get("top_k", 3)
        if not isinstance(top_k_value, int) or top_k_value <= 0:
            raise ConfigError("top_k must be a positive integer", extend_path(path, "top_k"))

        threshold_value = mapping.get("similarity_threshold", -1.0)
        if not isinstance(threshold_value, (int, float)):
            raise ConfigError("similarity_threshold must be numeric", extend_path(path, "similarity_threshold"))

        read_value = mapping.get("read", True)
        if not isinstance(read_value, bool):
            raise ConfigError("read must be boolean", extend_path(path, "read"))

        write_value = mapping.get("write", True)
        if not isinstance(write_value, bool):
            raise ConfigError("write must be boolean", extend_path(path, "write"))

        return cls(
            name=name,
            retrieve_stage=stages,
            top_k=top_k_value,
            similarity_threshold=float(threshold_value),

View on GitHub (pinned to 4fb2db0ea9)

Solutions

  1. Set top_k to a positive integer literal, e.g. 5
  2. Cast computed values with int(...) before building config
  3. Omit top_k to use the default of 3

Example fix

# before
top_k: 3.0
# after
top_k: 3
Defensive patterns

Strategy: validation

Validate before calling

tk = cfg.get('top_k', 3)
assert isinstance(tk, int) and not isinstance(tk, bool) and tk > 0, 'top_k invalid'

Type guard

def is_valid_top_k(v) -> bool:
    return isinstance(v, int) and not isinstance(v, bool) and v > 0

Try / catch

try:
    MemoryRetrieveConfig.from_dict(d, path='retrieve')
except ConfigError as e:
    if 'top_k' in str(e):
        d['top_k'] = int(d['top_k']) or 3
        MemoryRetrieveConfig.from_dict(d, path='retrieve')

Prevention

When it happens

Trigger: Setting top_k: 3.5, top_k: 0, top_k: -1, or top_k: '3' in a memory retrieve config.

Common situations: YAML floats (3.0) instead of ints; tuning scripts computing top_k as a float; reusing a threshold-style value for top_k; passing booleans (True is an int subclass but fails positivity only when 0/False cases arise — note isinstance(True, int) is True so True passes, but 0 fails).

Related errors


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