Panniantong/Agent-Reach · error · ValueError
limit must be non-negative
Error message
limit must be non-negative
What it means
XueqiuChannel.search (or the public-timeline helper at agent_reach/channels/xueqiu.py:239) validates its limit argument up front: a negative limit raises ValueError('limit must be non-negative') before any network call. Values 1..50 are accepted (anything above 50 is clamped with min(limit, 50)); 0 short-circuits to an empty list.
Source
Thrown at agent_reach/channels/xueqiu.py:239
}
)
return results
def get_hot_posts(self, limit: int = 20) -> list:
"""获取雪球热门帖子。
Uses the v4 public timeline endpoint which returns posts in a `list`
array. Each item carries a JSON-encoded `data` field containing the
actual post payload (title, description, user, like_count, target).
Args:
limit: 最多返回条数(上限 50)
Returns a list of dicts with keys:
id, title, text, author, likes, url
"""
if limit < 0:
raise ValueError("limit must be non-negative")
limit = min(limit, 50)
if limit == 0:
return []
data = _get_json(
"https://xueqiu.com/v4/statuses/public_timeline_by_category.json"
f"?since_id=-1&max_id=-1&count={limit}&category=-1"
)
items = data.get("list") or []
results = []
for item in items[:limit]:
# Each item.data is a JSON string containing the real post payload
try:
post = (
json.loads(item["data"])
if isinstance(item.get("data"), str)
else {}
)
except (json.JSONDecodeError, KeyError):View on GitHub (pinned to 93ae1d18c3)
Solutions
- Pass a non-negative limit; use 0 for 'nothing' and let the channel clamp anything over 50
- If -1 was meant as 'default', pass a concrete value like 20 instead
- Fix the arithmetic producing the negative value (e.g. max(0, remaining))
- Validate/validate user-supplied counts at your own CLI boundary with argparse type=int plus a min check
Example fix
# before results = channel.search(query, limit=page_size - offset) # can go negative # after results = channel.search(query, limit=max(0, page_size - offset))
Defensive patterns
Strategy: validation
Validate before calling
def safe_limit(requested: int) -> int:
"""Clamp to the xueqiu channel's accepted range before calling."""
return max(0, min(requested, 50))
results = channel.search(query, limit=safe_limit(user_count)) Type guard
def is_valid_xueqiu_limit(value: object) -> bool:
return isinstance(value, int) and not isinstance(value, bool) and value >= 0 Try / catch
try:
results = channel.search(query, limit=n)
except ValueError as exc:
if "non-negative" in str(exc):
results = channel.search(query, limit=abs(n)) # or reject input upstream
else:
raise Prevention
- Clamp user-supplied counts with max(0, min(n, 50)) at your own boundary
- Remember 0 is valid (empty result) and >50 is silently clamped — do not rely on exact counts above 50
- Never use -1 as a 'server default' sentinel here; pick a concrete page size
When it happens
Trigger: Calling the public timeline API with limit=-1 (e.g. code that computes limit as size - remaining and underflows, or treats -1 as 'default' like some APIs do). Note: the check is limit < 0, so limit=0 is valid and returns [].
Common situations: Porting code from APIs where -1 means 'server default' (xueqiu's own web API uses -1 sentinels for since_id/max_id); arithmetic that computes a negative count (10 - 20); passing an unvalidated CLI argument straight through.
Related errors
- agent-reach install: error: unknown channel(s): {unknown}. S
- Missing value for {args.key}
- 当前配置是只读的,不能保存
- Profile selection is supported only for {', '.join(PROFILE_S
- Profile '{scrub_url_credentials(profile)}' not found for {sc
AI-assisted analysis of Panniantong/Agent-Reach@93ae1d18c3 (2026-08-14).
Data as JSON: /api/errors/76231db784765f63.
Report an issue: GitHub.