{"record":{"id":"b5146dd4f8ce4a61","repo":"tinyhumansai/openhuman","slug":"agentworkapi-control-runid-is-required","errorCode":null,"errorMessage":"agentWorkApi.control: runId is required","messagePattern":"agentWorkApi\\.control: runId is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/src/services/api/agentWorkApi.ts","lineNumber":107,"sourceCode":"    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> => {\n    const runId = args.runId?.trim();\n    if (!runId) throw new Error('agentWorkApi.control: runId is required');\n    const message = args.message?.trim();\n    if ((args.action === 'continue' || args.action === 'follow_up') && !message) {\n      throw new Error(`agentWorkApi.control: ${args.action} requires a message`);\n    }\n    const params: Record<string, unknown> = { runId, action: args.action };\n    if (message) params.message = message;\n    const reason = args.reason?.trim();\n    if (reason) params.reason = reason;\n    log('control runId=%s action=%s', runId, args.action);\n    const response = await callCoreRpc<AgentWorkControlResponse>({\n      method: 'openhuman.agent_work_control',\n      params,\n    });\n    log('control received status=%s', response.row.status);\n    return response.row;\n  },\n};\n","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/app/src/services/api/agentWorkApi.ts#L89-L125","documentation":"Guard inside agentWorkApi.control: runId is trimmed and must be non-empty before the openhuman.agent_work_control RPC applies the control verb (continue / follow_up / stop). A blank id cannot identify a run, so the client rejects it before the network hop.","triggerScenarios":"Calling control({ runId: '', action: 'stop' }) or control({ runId: '  ', action: 'continue', message: 'hi' }) — whitespace-only ids are trimmed to empty and rejected; also control({ action: 'stop' }) with no runId at all.","commonSituations":"A control button wired to a selected-run state that is null until a row is clicked; the run finishing and being removed from the list between selection and action; ids read from an optional column that some rows lack.","solutions":["Disable control buttons until a run row is selected","Read the runId from the row the action was triggered on, not from a possibly-stale selected id","Treat a vanished run as a no-op in the UI (list refresh) rather than calling with an empty id"],"exampleFix":"// before\nonStop={() => agentWorkApi.control({ runId: selectedRunId ?? '', action: 'stop' })}\n\n// after\nonStop={() => {\n  if (!selectedRunId) return;\n  agentWorkApi.control({ runId: selectedRunId, action: 'stop' }).then(refresh).catch(notify);\n}}","handlingStrategy":"validation","validationCode":"const runId = args?.runId?.trim();\nif (runId) await agentWorkApi.control({ runId, action });","typeGuard":"const isNonEmptyTrimmed = (v: unknown): v is string => typeof v === 'string' && v.trim().length > 0;","tryCatchPattern":"try { await agentWorkApi.control({ runId, action }); }\ncatch (e) { if (String(e.message).includes('runId is required')) refreshRuns(); else throw e; }","preventionTips":["Disable control buttons until a run row is selected","Pass the row's id directly from the action event, not a stale selection variable","Refresh the list when a run disappears — treat missing runs as no-ops"],"tags":["validation","agent-work","required-field"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}