HKUDS/Vibe-Trading · error · ValueError

evidence limit must be positive

Error message

evidence limit must be positive

What it means

list_evidence validates its optional limit argument: if limit is not None it must be > 0, else ValueError('evidence limit must be positive'). The limit backs a SQL TOP/LIMIT clause, and 0 or negative values are treated as caller bugs rather than 'return nothing'.

Source

Thrown at agent/src/goal/store.py:517

    @_synchronized
    def list_claims(self, goal_id: str) -> list[GoalClaim]:
        """Return claims for a goal."""
        rows = self._conn.execute(
            """
            SELECT * FROM goal_claims
            WHERE goal_id = ?
            ORDER BY created_at, claim_id
            """,
            (normalize_required_text(goal_id, "goal_id"),),
        ).fetchall()
        return [self._claim_from_row(row) for row in rows]

    @_synchronized
    def list_evidence(self, goal_id: str, limit: int | None = None) -> list[EvidenceRecord]:
        """Return evidence rows for a goal."""
        goal_id = normalize_required_text(goal_id, "goal_id")
        if limit is not None and limit <= 0:
            raise ValueError("evidence limit must be positive")
        if limit is not None:
            rows = self._conn.execute(
                """
                SELECT * FROM (
                    SELECT * FROM goal_evidence
                    WHERE goal_id = ?
                    ORDER BY created_at DESC, evidence_id DESC
                    LIMIT ?
                )
                ORDER BY created_at, evidence_id
                """,
                (goal_id, limit),
            ).fetchall()
            return [self._evidence_from_row(row) for row in rows]
        rows = self._conn.execute(
            """
            SELECT * FROM goal_evidence
            WHERE goal_id = ?

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Pass None (or omit limit) when you want all evidence rows
  2. Use max(1, limit) if a clamped small limit is acceptable
  3. Fix pagination to guard page >= 1 and size >= 1 before computing the limit
  4. Validate limits at the API boundary with a clear message naming the parameter

Example fix

# before
evidence = store.list_evidence(goal_id, limit=0)
# after
evidence = store.list_evidence(goal_id, limit=None)
Defensive patterns

Strategy: validation

Validate before calling

def clean_limit(v):
    return None if v is None else max(1, int(v))

rows = store.list_evidence(goal_id, limit=clean_limit(limit))

Type guard

def is_valid_limit(v) -> bool:
    return v is None or (isinstance(v, int) and not isinstance(v, bool) and v > 0)

Try / catch

try:
    rows = store.list_evidence(goal_id, limit=limit)
except ValueError as e:
    if 'limit must be positive' in str(e):
        rows = store.list_evidence(goal_id, limit=None)
    else:
        raise

Prevention

When it happens

Trigger: Calling store.list_evidence(goal_id, limit=0) (a common 'default' from configs) or with a negative limit; get_goal_snapshot forwards a limit it received, so a bad limit there surfaces here.

Common situations: Config/UI defaults of 0 intended as 'no limit' — this API uses None for that; pagination math like (page-1)*size producing 0 on page 1 or negatives past the end; env-var parsing yielding 0.

Related errors


AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28). Data as JSON: /api/errors/31c0ecb84dbc67fb. Report an issue: GitHub.