bytedance/deer-flow · error · ValueError

confidence

Error message

confidence

What it means

_validate_confidence() enforces that a fact's confidence is a finite number in [0, 1] before it is persisted, so stored JSON stays standards-compliant (no NaN/Infinity) and downstream max()/comparison arithmetic is safe. math.isfinite(NaN) is False and out-of-range values are rejected. The terse 'confidence' message is the deliberate contract.

Source

Thrown at backend/packages/harness/deerflow/agents/memory/backends/deermem/deermem/core/updater.py:54

# context.  Unlike the previous asyncio.run() approach, this runs *sync*
# model.invoke() calls — no event loop is created, so the langchain async
# httpx client pool (globally cached via @lru_cache) is never touched and
# cross-loop connection reuse is impossible.
_SYNC_MEMORY_UPDATER_EXECUTOR = concurrent.futures.ThreadPoolExecutor(
    max_workers=4,
    thread_name_prefix="memory-updater-sync",
)
atexit.register(lambda: _SYNC_MEMORY_UPDATER_EXECUTOR.shutdown(wait=False))


# Data-access + fact-CRUD functions (_save_memory_to_file / get_memory_data /
# reload_memory_data / import_memory_data / clear_memory_data / create_memory_fact /
# delete_memory_fact / update_memory_fact) moved into MemoryUpdater as instance
# methods (use self._storage). See the class below.
def _validate_confidence(confidence: float) -> float:
    """Validate persisted fact confidence so stored JSON stays standards-compliant."""
    if not math.isfinite(confidence) or confidence < 0 or confidence > 1:
        raise ValueError("confidence")
    return confidence


def _coerce_source_confidence(fact: dict[str, Any]) -> float:
    """Return a stored fact's confidence as a finite float in [0, 1], defaulting to 0.5.

    dict.get(key, default) returns the stored value (including None) when the key
    exists, so a fact written with "confidence": null would propagate None into
    arithmetic and crash max(). This helper guards against null, bool, non-numeric,
    and non-finite values from corrupted or manually edited memory files.
    """
    raw = fact.get("confidence")
    if raw is None or isinstance(raw, bool):
        return 0.5
    try:
        val = float(raw)
    except (TypeError, ValueError):
        return 0.5

View on GitHub (pinned to 1dd6ba1acb)

Solutions

  1. Clamp and coerce before saving: confidence = min(1.0, max(0.0, float(confidence))).
  2. If the source uses percentages, divide by 100 at the boundary.
  3. Guard NaN explicitly: if not math.isfinite(x): use the 0.5 default.
  4. Validate the whole fact with a pydantic model using Field(ge=0, le=1, allow_inf_nan=False).

Example fix

# before
fact = {"content": text, "confidence": llm_score}  # llm_score in 0..100 or NaN

# after
score = float(llm_score) if llm_score is not None and math.isfinite(float(llm_score)) else 0.5
fact = {"content": text, "confidence": min(1.0, max(0.0, score / 100.0 if score > 1 else score))}
Defensive patterns

Strategy: validation

Validate before calling

def safe_confidence(raw) -> float:
    try:
        value = float(raw)
    except (TypeError, ValueError):
        return 0.5
    if not math.isfinite(value):
        return 0.5
    if value > 1 and value <= 100:  # percentage heuristic
        value /= 100.0
    return min(1.0, max(0.0, value))

fact["confidence"] = safe_confidence(fact.get("confidence"))

Type guard

def is_valid_confidence(v: object) -> TypeGuard[float]:
    return isinstance(v, (int, float)) and not isinstance(v, bool) and math.isfinite(v) and 0 <= v <= 1

Prevention

When it happens

Trigger: create/update fact paths passing confidence=float('nan'), float('inf'), -0.5, 1.2, or a non-float that reaches math.isfinite (e.g. a string if type coercion was skipped upstream).

Common situations: LLM emitting confidence as a percentage (0-100) instead of a fraction; parsing confidence from user input or JSON strings like '0.8'; NaN leaking from arithmetic on missing values (0/0).

Related errors


AI-assisted analysis of bytedance/deer-flow@1dd6ba1acb (2026-08-14). Data as JSON: /api/errors/4e70161c17ce0655. Report an issue: GitHub.