{"record":{"id":"0a245fcec23ef2c4","repo":"tinyhumansai/openhuman","slug":"agentworkapi-list-limit-must-be-a-positive-intege","errorCode":null,"errorMessage":"agentWorkApi.list: limit must be a positive integer","messagePattern":"agentWorkApi\\.list: limit must be a positive integer","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/src/services/api/agentWorkApi.ts","lineNumber":87,"sourceCode":"  /** Optional note recorded when `stop`ping. */\n  reason?: string;\n}\n\n/** Response from `openhuman.agent_work_control`: the re-projected row. */\ninterface AgentWorkControlResponse {\n  row: AgentWorkRow;\n}\n\nexport const agentWorkApi = {\n  /**\n   * List all tracked background agent runs, grouped by lifecycle bucket.\n   *\n   * @param limit Optional cap on the number of rows returned (newest first,\n   *   applied server-side). Omit to use the handler default.\n   */\n  list: async (limit?: number): Promise<AgentWorkResponse> => {\n    if (limit !== undefined && (!Number.isInteger(limit) || limit <= 0)) {\n      throw new Error('agentWorkApi.list: limit must be a positive integer');\n    }\n    log('list limit=%o', limit);\n    const response = await callCoreRpc<AgentWorkResponse>({\n      method: 'openhuman.agent_work_list',\n      params: limit === undefined ? {} : { limit },\n    });\n    log('list received groups=%d total=%d', response.groups.length, response.total);\n    return response;\n  },\n\n  /**\n   * Apply a control verb to one background agent run, returning the updated row.\n   *\n   * `continue` and `follow_up` carry the user's message; the client rejects an\n   * empty message for those verbs before hitting core (the Rust handler also\n   * enforces it). `stop` may carry an optional `reason`.\n   */\n  control: async (args: AgentWorkControlArgs): Promise<AgentWorkRow> => {","sourceCodeStart":69,"sourceCodeEnd":105,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/app/src/services/api/agentWorkApi.ts#L69-L105","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass undefined instead of 0 when you want the server default","Clamp computed limits: Math.max(1, Math.floor(limit))","Validate the source of the number (input field, persisted setting) before it reaches the call"],"exampleFix":"// before\nconst res = await agentWorkApi.list(count); // count === 0 on empty dashboard\n\n// after\nconst res = await agentWorkApi.list(count > 0 ? Math.floor(count) : undefined);","handlingStrategy":"validation","validationCode":"const safeLimit = (v: number | undefined) => v === undefined ? undefined : (Number.isInteger(v) && v > 0 ? v : undefined);\nconst res = await agentWorkApi.list(safeLimit(limit));","typeGuard":"const isPositiveInt = (v: unknown): v is number => typeof v === 'number' && Number.isInteger(v) && v > 0;","tryCatchPattern":"try { await agentWorkApi.list(limit); }\ncatch (e) { if (String(e.message).includes('positive integer')) await agentWorkApi.list(); else throw e; }","preventionTips":["Never derive limit from an array length that can be 0","Clamp persisted page-size settings on read, not just on write","Pass undefined, not 0, to mean 'handler default'"],"tags":["validation","pagination","agent-work"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}