paperclipai/paperclip · error

Name the reviewer's exact agent ID in targetAgentId.

Error message

Name the reviewer's exact agent ID in targetAgentId.

What it means

This guard in nativeCompletionFeedback validates attention requests raised by a worker agent reporting task completion. When the request names a reviewer (ownerClass 'agent') but targetAgentId is missing or is not a UUID v4-shaped string, the runtime rejects the completion feedback so the worker names a precise reviewer instead of an unresolvable target. It forces agents to supply machine-resolvable reviewer identity.

Solutions

  1. Copy the reviewer's exact agent ID (UUID format) from the company's agent list into targetAgentId
  2. If no specific reviewer is needed, omit the agent-owned attention request instead of sending ownerClass:'agent' without an ID
  3. If targeting the run's own agent is intended, note that self-review is separately rejected (line 155) — pick a different agent

Example fix

// before
{ ownerClass: "agent", targetAgentId: "qa-agent" }
// after
{ ownerClass: "agent", targetAgentId: "3f2a9c1e-8b4d-4a2f-9c1e-8b4d4a2f9c1e" }
Defensive patterns

Strategy: validation

Validate before calling

const UUID_RE = /^[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i;
if (req.ownerClass === "agent" && (!req.targetAgentId || !UUID_RE.test(req.targetAgentId) || req.targetAgentId === run.agentId)) {
  throw new Error("Set targetAgentId to a different agent's exact UUID.");
}

Type guard

const isValidAgentTarget = (r) => r.ownerClass !== "agent" || (typeof r.targetAgentId === "string" && /^[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i.test(r.targetAgentId));

Try / catch

try { await feedback(payload); } catch (e) { if (e.message.includes("exact agent ID")) { /* fix targetAgentId to a valid UUID and retry */ } else throw e; }

Prevention

When it happens

Trigger: Calling nativeCompletionFeedback (via feedback/backend) with signals.actionableAttentionRequests containing {ownerClass:'agent', targetAgentId: undefined} or a non-UUID value like 'the reviewer agent', 'agent-2', or a truncated ID.

Common situations: An LLM writes prose like 'request review from the QA agent' into targetAgentId instead of copying the exact UUID; agent omits targetAgentId while setting ownerClass:'agent'; model hallucinates a malformed ID.

Understand the failure class

Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.

Related errors


AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-09-18). Data as JSON: /api/errors/a9d5628b58bdbe83. Report an issue: GitHub.

Appendix: source

Thrown at server/src/services/native-runtime/native-completion-feedback.ts:155

  const readiness = await issueService(db).getDependencyReadiness(issue.id, db);
  if (readiness.unresolvedBlockerCount > 0) {
    return `Completion report accepted; this task still has unresolved dependencies. Explain the blockers on [this task](/issues/${issue.identifier ?? issue.id}); do not say the task is done.`;
  }
  if (
    result.reportedWorkDisposition === "needs_review" &&
    signals.actionableAttentionRequests.length === 0
  ) {
    throw new Error(
      "needs_review requires a concrete decision and a named reviewer in attentionRequests. Continue unfinished work or checks; report done when complete. Paperclip will not create an automatic completion approval.",
    );
  }
  for (const request of signals.actionableAttentionRequests) {
    if (request.ownerClass !== "agent") continue;
    if (request.targetAgentId === run.agentId) {
      throw new Error("Name a different agent to review this task. A worker cannot review its own completion.");
    }
    if (!request.targetAgentId || !/^[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f]{12}$/i.test(request.targetAgentId)) {
      throw new Error("Name the reviewer's exact agent ID in targetAgentId.");
    }
    const reviewer = await db.select().from(agents).where(and(
      eq(agents.id, request.targetAgentId), eq(agents.companyId, run.companyId),
    )).limit(1).then((rows) => rows[0]);
    if (!reviewer || !(await evaluateAgentInvokabilityFromDb(db, reviewer)).invokable) {
      throw new Error("The named reviewer is not available in this company. Choose an available reviewer or report the concrete blocker.");
    }
  }
  return "Completion report accepted. Task status will be committed after this turn and workspace finalization finish. Describe the completed work and any explicitly requested reviewer action; do not claim an approval is needed unless one was requested.";
}

View on GitHub (pinned to 3f1d897a7c)