{"record":{"id":"0206a67440db11f5","repo":"tinyhumansai/openhuman","slug":"agentteamapi-listmessages-teamid-is-required","errorCode":null,"errorMessage":"agentTeamApi.listMessages: teamId is required","messagePattern":"agentTeamApi\\.listMessages: teamId is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"app/src/services/api/agentTeamApi.ts","lineNumber":215,"sourceCode":"   */\n  get: async (teamId: string): Promise<TeamView | null> => {\n    if (!teamId) throw new Error('agentTeamApi.get: teamId is required');\n    log('get teamId=%s', teamId);\n    const response = await callCoreRpc<{ team: TeamView | null }>({\n      method: 'openhuman.agent_team_get',\n      params: { teamId },\n    });\n    log('get found=%o', response.team != null);\n    return response.team ?? null;\n  },\n\n  /**\n   * List a team's teammate messages in sequence order. Unwraps the\n   * `{ messages }` envelope and narrows each run-event payload to a typed\n   * {@link TeamMessagePayload}.\n   */\n  listMessages: async (teamId: string, limit?: number): Promise<TeamMessage[]> => {\n    if (!teamId) throw new Error('agentTeamApi.listMessages: teamId is required');\n    assertPositiveInt(limit, 'limit');\n    log('listMessages teamId=%s limit=%o', teamId, limit);\n    const response = await callCoreRpc<{ messages?: RawRunEvent[] }>({\n      method: 'openhuman.agent_team_list_messages',\n      params: limit === undefined ? { teamId } : { teamId, limit },\n    });\n    const messages = (response.messages ?? []).map(event => ({\n      runId: event.runId,\n      sequence: event.sequence,\n      eventType: event.eventType,\n      payload: readMessagePayload(event.payload),\n      timestamp: event.timestamp,\n    }));\n    log('listMessages received=%d', messages.length);\n    return messages;\n  },\n\n  /**","sourceCodeStart":197,"sourceCodeEnd":233,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/app/src/services/api/agentTeamApi.ts#L197-L233","documentation":"Guard inside agentTeamApi.listMessages: the team id must be a non-empty string before the openhuman.agent_team_list_messages RPC is issued. The same call also runs assertPositiveInt on the optional limit, so a bad limit surfaces as the 'must be a positive integer' error instead.","triggerScenarios":"Calling listMessages('') or listMessages(someUndefinedId) — e.g. a message pane mounted before the team is chosen, or a teamId prop that defaults to empty string.","commonSituations":"Chat/transcript components that load in parallel with the team selector; destructuring teamId from an object where the key is absent; race where the team is deleted while the view is open and state resets to ''.","solutions":["Gate the fetch on a truthy teamId in the component (skip or show empty state)","Initialize team-dependent state to null/undefined, not '', and check it before calling","Re-derive the id from the route/store right before the call rather than caching it in local state"],"exampleFix":"// before\nconst msgs = await agentTeamApi.listMessages(teamId ?? '');\n\n// after\nif (!teamId) return [];\nconst msgs = await agentTeamApi.listMessages(teamId);","handlingStrategy":"validation","validationCode":"if (typeof teamId === 'string' && teamId && Number.isInteger(limit ?? 1)) {\n  const msgs = await agentTeamApi.listMessages(teamId, limit);\n}","typeGuard":"const isNonEmptyString = (v: unknown): v is string => typeof v === 'string' && v.length > 0;","tryCatchPattern":"try { const msgs = await agentTeamApi.listMessages(teamId, limit); }\ncatch (e) { if (String(e.message).includes('teamId is required')) return []; else throw e; }","preventionTips":["Skip message-pane queries until the team context is resolved","Keep limit clamping in one pagination helper","Reset message state when the selected team id clears"],"tags":["validation","agent-teams","required-field"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}