wavetermdev/waveterm · error
count must be positive
Error message
count must be positive
What it means
parseTermGetScrollbackInput rejects a negative count with this sentinel error after defaulting a zero count to 200 and clamping to MaxCount (1000). Note the message says 'must be positive' but the check is result.Count < 0, so only negative values trigger it — 0 is treated as 'use default'. It guards the scrollback RPC against nonsensical line counts.
Source
Thrown at pkg/aiusechat/tools_term.go:76
result.Count = DefaultCount
return result, nil
}
inputBytes, err := json.Marshal(input)
if err != nil {
return nil, fmt.Errorf("failed to marshal input: %w", err)
}
if err := json.Unmarshal(inputBytes, result); err != nil {
return nil, fmt.Errorf("failed to unmarshal input: %w", err)
}
if result.Count == 0 {
result.Count = DefaultCount
}
if result.Count < 0 {
return nil, fmt.Errorf("count must be positive")
}
result.Count = min(result.Count, MaxCount)
return result, nil
}
func getTermScrollbackOutput(tabId string, widgetId string, rpcData wshrpc.CommandTermGetScrollbackLinesData) (*TermGetScrollbackToolOutput, error) {
ctx, cancelFn := context.WithTimeout(context.Background(), 5*time.Second)
defer cancelFn()
fullBlockId, err := wcore.ResolveBlockIdFromPrefix(ctx, tabId, widgetId)
if err != nil {
return nil, err
}
rpcClient := wshclient.GetBareRpcClient()
result, err := wshclient.TermGetScrollbackLinesCommand(View on GitHub (pinned to a4447c1563)
Solutions
- Pass count >= 1, or omit count entirely to get the default of 200
- If you want 'the last N lines', use line_start: 0 with count: N, not a negative count
- Clamp user/model-supplied counts to [1, 1000] before invoking the tool
- If you believe 0 should be an error or negative counts should wrap, adjust the validation — but as a caller, never send negatives
Example fix
// before
{"widget_id": "b1a2c3d4", "count": -10}
// after
{"widget_id": "b1a2c3d4", "line_start": 0, "count": 10} Defensive patterns
Strategy: validation
Validate before calling
if count, ok := inputMap["count"]; ok {
if n, ok := count.(float64); ok && (n < 1 || n != float64(int(n))) {
return fmt.Errorf("count must be an integer >= 1")
}
} Type guard
func validCount(n int) bool { return n >= 1 && n <= 1000 } Try / catch
parsed, err := parseTermGetScrollbackInput(input)
if err != nil {
if strings.Contains(err.Error(), "count must be positive") {
return nil, fmt.Errorf("invalid tool argument: send count >= 1 or omit it (default 200)")
}
return nil, err
} Prevention
- Enforce InputSchema minimum: 1 for count before invoking the tool
- To page backward, increase line_start, never use negative count
- Clamp client-side to [1, 1000] since the tool clamps to MaxCount anyway
When it happens
Trigger: term_get_scrollback called with {"count": -1} (or any negative integer) in the tool arguments.
Common situations: AI model hallucinating a negative count (e.g. count: -10 intending 'last 10 lines'); off-by-sign logic in code that programmatically builds tool input; confusing line indexing direction (0 = most recent) with negative offsets.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- block %s is not a terminal block (view type: %s)
- failed to unmarshal input: %w
- failed to get terminal scrollback: %w
- invalid term size: %v
- missing zone file info for ${zoneId}:${fileName}
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/cddc2083d4c2131b.
Report an issue: GitHub.