tinyhumansai/openhuman · error

agentTeamApi.listMessages: teamId is required

Error message

agentTeamApi.listMessages: teamId is required

What it means

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.

Source

Thrown at app/src/services/api/agentTeamApi.ts:215

   */
  get: async (teamId: string): Promise<TeamView | null> => {
    if (!teamId) throw new Error('agentTeamApi.get: teamId is required');
    log('get teamId=%s', teamId);
    const response = await callCoreRpc<{ team: TeamView | null }>({
      method: 'openhuman.agent_team_get',
      params: { teamId },
    });
    log('get found=%o', response.team != null);
    return response.team ?? null;
  },

  /**
   * List a team's teammate messages in sequence order. Unwraps the
   * `{ messages }` envelope and narrows each run-event payload to a typed
   * {@link TeamMessagePayload}.
   */
  listMessages: async (teamId: string, limit?: number): Promise<TeamMessage[]> => {
    if (!teamId) throw new Error('agentTeamApi.listMessages: teamId is required');
    assertPositiveInt(limit, 'limit');
    log('listMessages teamId=%s limit=%o', teamId, limit);
    const response = await callCoreRpc<{ messages?: RawRunEvent[] }>({
      method: 'openhuman.agent_team_list_messages',
      params: limit === undefined ? { teamId } : { teamId, limit },
    });
    const messages = (response.messages ?? []).map(event => ({
      runId: event.runId,
      sequence: event.sequence,
      eventType: event.eventType,
      payload: readMessagePayload(event.payload),
      timestamp: event.timestamp,
    }));
    log('listMessages received=%d', messages.length);
    return messages;
  },

  /**

View on GitHub (pinned to a221052e0d)

Solutions

  1. Gate the fetch on a truthy teamId in the component (skip or show empty state)
  2. Initialize team-dependent state to null/undefined, not '', and check it before calling
  3. Re-derive the id from the route/store right before the call rather than caching it in local state

Example fix

// before
const msgs = await agentTeamApi.listMessages(teamId ?? '');

// after
if (!teamId) return [];
const msgs = await agentTeamApi.listMessages(teamId);
Defensive patterns

Strategy: validation

Validate before calling

if (typeof teamId === 'string' && teamId && Number.isInteger(limit ?? 1)) {
  const msgs = await agentTeamApi.listMessages(teamId, limit);
}

Type guard

const isNonEmptyString = (v: unknown): v is string => typeof v === 'string' && v.length > 0;

Try / catch

try { const msgs = await agentTeamApi.listMessages(teamId, limit); }
catch (e) { if (String(e.message).includes('teamId is required')) return []; else throw e; }

Prevention

When it happens

Trigger: 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.

Common situations: 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 ''.

Related errors


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