tinyhumansai/openhuman · error

agentTeamApi.completeTask: teamId, taskId and memberId are r

Error message

agentTeamApi.completeTask: teamId, taskId and memberId are required

What it means

Guard inside agentTeamApi.completeTask: all three identifiers (teamId, taskId, memberId) must be non-empty before the openhuman.agent_team_complete_task RPC runs. Any missing one means the caller cannot identify the completion target, so the client fails fast.

Source

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

  },

  /**
   * Complete a claimed task, gating its transition to `done`. The core checks
   * the quality invariants (dependencies done, the completer is the claimant and
   * any pre-assigned owner, evidence present when `requireEvidence`) and returns
   * a {@link CompletionOutcome}: `completed`, `gateFailed` (with reasons),
   * `notClaimed`, or `unknownTask`. Evidence links accumulate across retries.
   */
  completeTask: async (params: {
    teamId: string;
    taskId: string;
    memberId: string;
    evidence?: string[];
    requireEvidence?: boolean;
  }): Promise<CompletionOutcome> => {
    const { teamId, taskId, memberId, evidence = [], requireEvidence = false } = params;
    if (!teamId || !taskId || !memberId) {
      throw new Error('agentTeamApi.completeTask: teamId, taskId and memberId are required');
    }
    log('completeTask teamId=%s taskId=%s requireEvidence=%o', teamId, taskId, requireEvidence);
    const response = await callCoreRpc<{ result: CompletionOutcome }>({
      method: 'openhuman.agent_team_complete_task',
      params: { teamId, taskId, memberId, evidence, requireEvidence },
    });
    log('completeTask kind=%s', response.result.kind);
    return response.result;
  },

  /**
   * Stop a member and release any task it is actively working on back to `todo`.
   * Returns the stopped member plus the ids that were released.
   */
  shutdownMember: async (teamId: string, memberId: string): Promise<MemberShutdown> => {
    if (!teamId || !memberId) {
      throw new Error('agentTeamApi.shutdownMember: teamId and memberId are required');
    }

View on GitHub (pinned to a221052e0d)

Solutions

  1. Disable/withhold the complete action until all three ids are populated
  2. Build the params from a single resolved task-with-member object so the fields cannot drift apart
  3. Add a component-level check so the user gets feedback instead of a thrown error

Example fix

// before
await agentTeamApi.completeTask({ teamId, taskId: task.id }); // memberId missing

// after
if (!task.memberId) throw new Error('Task has no assigned member yet');
await agentTeamApi.completeTask({ teamId, taskId: task.id, memberId: task.memberId });
Defensive patterns

Strategy: validation

Validate before calling

const canComplete = Boolean(teamId && task?.id && task?.memberId);
if (canComplete) await agentTeamApi.completeTask({ teamId, taskId: task.id, memberId: task.memberId });

Type guard

const isCompleteTaskArgs = (a: { teamId?: string; taskId?: string; memberId?: string }): boolean =>
  [a.teamId, a.taskId, a.memberId].every(v => typeof v === 'string' && v.length > 0);

Try / catch

try { await agentTeamApi.completeTask(params); }
catch (e) { if (String(e.message).includes('are required')) disableCompleteButton(); else throw e; }

Prevention

When it happens

Trigger: Calling completeTask({ teamId, taskId }) with memberId omitted; passing a task row whose member assignment has not loaded yet; iterating tasks where some rows lack a claimedBy/member field.

Common situations: A 'Mark complete' button enabled before the task-member join data resolves; forms built from partial state; copy-pasting a call template and forgetting one field.

Related errors


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