crewAIInc/crewAI · error · ValueError
seconds must be zero or greater, got {seconds:g}.
Error message
seconds must be zero or greater, got {seconds:g}. What it means
WaitTool's duration validator rejects negative wait times. A negative duration is meaningless for sleep() and usually signals a sign error or misparsed value upstream, so it fails fast with a message echoing the offending number (%g formatting).
Source
Thrown at lib/crewai-tools/src/crewai_tools/tools/wait_tool/wait_tool.py:177
``BaseTool.run`` skips ``args_schema`` validation when called with
positional arguments, so the bounds are enforced here too rather than
left to ``time.sleep`` to reject. Infinity is a valid request: it clamps
to the cap like any other oversized wait.
Args:
seconds: The requested wait duration.
Returns:
A tuple of the duration to actually wait and whether it was capped.
Raises:
ValueError: If ``seconds`` is negative or not a number.
"""
if math.isnan(seconds):
raise ValueError("seconds must be a number, got NaN.")
if seconds < 0:
raise ValueError(f"seconds must be zero or greater, got {seconds:g}.")
if seconds > self.max_seconds:
return self.max_seconds, True
return seconds, False
def _format_result(
self, waited: float, requested: float, reason: str | None
) -> str:
"""Describe the completed wait back to the model.
Args:
waited: The duration actually waited.
requested: The duration the model asked for.
reason: Optional note on what is being waited for.
Returns:
A summary of how long was waited and whether the request was capped.
"""
parts = [f"Waited {_format_seconds(waited)}."]View on GitHub (pinned to 754d7323be)
Solutions
- Clamp to zero (or a small positive floor) before calling: seconds = max(0.0, seconds).
- Fix the sign logic upstream (swap operands of the subtraction, use abs() only if direction is irrelevant).
- Add a minimum/maximum constraint in the tool description so the model is steered to non-negative values.
Example fix
# before seconds = end - start # accidentally negative tool.run(seconds=seconds) # ValueError: must be zero or greater # after seconds = max(0.0, end - start) tool.run(seconds=seconds)
Defensive patterns
Strategy: validation
Validate before calling
def clamp_seconds(v) -> float:
try:
f = float(v)
except (TypeError, ValueError):
return 0.0
return max(0.0, f)
# seconds = clamp_seconds(raw) before WaitTool Type guard
import math
def is_non_negative_number(v) -> bool:
try:
f = float(v)
except (TypeError, ValueError):
return False
return not math.isnan(f) and f >= 0 Try / catch
try:
tool.run(seconds=raw)
except ValueError as e:
if 'zero or greater' in str(e):
tool.run(seconds=abs(float(raw))) # or 0.0; log the sign error
else:
raise Prevention
- Clamp durations with max(0.0, x) at the caller boundary.
- Check time-delta arithmetic for operand order before feeding results to waits.
- Constrain the tool schema/description to non-negative numbers to steer the model.
When it happens
Trigger: An agent or caller invoking wait with a negative number (wait(seconds=-5)), or arithmetic that yields a negative value such as end_time - start_time with the operands swapped, or '-30' parsed from model output.
Common situations: LLMs emitting negative durations in tool calls; time-delta math where a countdown goes below zero; timezone/DST arithmetic producing negative intervals.
Related errors
- seconds must be a number, got NaN.
- Project name '{name}' would generate folder name '{folder_na
- Project name '{name}' contains no valid characters for a Pyt
- Project name '{name}' would generate class name '{class_name
- Project name '{name}' would generate class name '{class_name
AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15).
Data as JSON: /api/errors/b567a24402b5d2ca.
Report an issue: GitHub.