tinyhumansai/openhuman · error

agentWorkApi.list: limit must be a positive integer

Error message

agentWorkApi.list: limit must be a positive integer

What it means

Client-side validation in agentWorkApi.list: an explicitly-supplied limit must be an integer greater than zero before the openhuman.agent_work_list RPC is issued. Omitting limit entirely is valid (the handler default applies); only a defined-but-bad value throws.

Source

Thrown at app/src/services/api/agentWorkApi.ts:87

  /** Optional note recorded when `stop`ping. */
  reason?: string;
}

/** Response from `openhuman.agent_work_control`: the re-projected row. */
interface AgentWorkControlResponse {
  row: AgentWorkRow;
}

export const agentWorkApi = {
  /**
   * List all tracked background agent runs, grouped by lifecycle bucket.
   *
   * @param limit Optional cap on the number of rows returned (newest first,
   *   applied server-side). Omit to use the handler default.
   */
  list: async (limit?: number): Promise<AgentWorkResponse> => {
    if (limit !== undefined && (!Number.isInteger(limit) || limit <= 0)) {
      throw new Error('agentWorkApi.list: limit must be a positive integer');
    }
    log('list limit=%o', limit);
    const response = await callCoreRpc<AgentWorkResponse>({
      method: 'openhuman.agent_work_list',
      params: limit === undefined ? {} : { limit },
    });
    log('list received groups=%d total=%d', response.groups.length, response.total);
    return response;
  },

  /**
   * Apply a control verb to one background agent run, returning the updated row.
   *
   * `continue` and `follow_up` carry the user's message; the client rejects an
   * empty message for those verbs before hitting core (the Rust handler also
   * enforces it). `stop` may carry an optional `reason`.
   */
  control: async (args: AgentWorkControlArgs): Promise<AgentWorkRow> => {

View on GitHub (pinned to a221052e0d)

Solutions

  1. Pass undefined instead of 0 when you want the server default
  2. Clamp computed limits: Math.max(1, Math.floor(limit))
  3. Validate the source of the number (input field, persisted setting) before it reaches the call

Example fix

// before
const res = await agentWorkApi.list(count); // count === 0 on empty dashboard

// after
const res = await agentWorkApi.list(count > 0 ? Math.floor(count) : undefined);
Defensive patterns

Strategy: validation

Validate before calling

const safeLimit = (v: number | undefined) => v === undefined ? undefined : (Number.isInteger(v) && v > 0 ? v : undefined);
const res = await agentWorkApi.list(safeLimit(limit));

Type guard

const isPositiveInt = (v: unknown): v is number => typeof v === 'number' && Number.isInteger(v) && v > 0;

Try / catch

try { await agentWorkApi.list(limit); }
catch (e) { if (String(e.message).includes('positive integer')) await agentWorkApi.list(); else throw e; }

Prevention

When it happens

Trigger: Calling agentWorkApi.list(0), list(-1), list(10.5), or list(NaN) — e.g. a page-size constant set to 0, or a computed cap that collapses to 0 when the work list is empty.

Common situations: Pagination counters derived from array lengths (limit = items.length when empty); query-string parsing that yields NaN; float page sizes from a percentage-based setting.

Related errors


AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16). Data as JSON: /api/errors/0a245fcec23ef2c4. Report an issue: GitHub.