paperclipai/paperclip · error

The done report includes unfinished work, failed…

Error message

The done report includes unfinished work, failed verification, or an outstanding decision. Finish the work or report the concrete blocker/reviewer request. No human completion approval was created.

What it means

A 'done' completion report is rejected when its own contents contradict completion: any remaining-work entry with blocksCompletion=true, a verification signal with status 'failed', or any actionable attention requests. Paperclip refuses to create a human completion approval from a self-contradictory done report.

Solutions

  1. Resolve or remove blocking remainingWork entries, or mark them non-blocking only if genuinely complete.
  2. Fix the failing verification checks before reporting done, or report blocked with the concrete failure.
  3. Resolve all attention requests (or reclassify them as non-actionable) before claiming done.
  4. Report a non-done disposition (blocked/needs follow-up) until the report is internally consistent with completion.

Example fix

// before
result.completionClaim.remainingWork.push({ description: "flaky test", blocksCompletion: true });
result.reportedWorkDisposition = "done";
// after
result.completionClaim.remainingWork = result.completionClaim.remainingWork.filter(w => !w.blocksCompletion);
// or report blocked if the flaky test still stands
result.reportedWorkDisposition = "blocked";
Defensive patterns

Strategy: validation

Validate before calling

const blocking = result.completionClaim.remainingWork.some(w => w.blocksCompletion);
const failedCheck = result.verificationSignals.some(v => v.status === "failed");
if (result.reportedWorkDisposition === "done" && (blocking || failedCheck || result.attentionRequests.length > 0)) {
  throw new Error("done report contradicts its own contents");
}

Try / catch

try { await reportCompletion({ runId, result }); } catch (e) { if (e.message.startsWith("The done report includes unfinished work")) { result.reportedWorkDisposition = "blocked"; return reportCompletion({ runId, result }); } throw e; }

Prevention

When it happens

Trigger: Agent reports disposition 'done' while result.completionClaim.remainingWork contains a blocking entry; verification checks reported status 'failed'; normalizePrpResultSignals yields actionableAttentionRequests.length > 0 alongside a done claim.

Common situations: Agents summarizing leftovers in remainingWork but still claiming done; failing test runs included in the verification section of an otherwise done report; attention requests (questions, reviewer asks) left open while claiming completion.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

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

    }
    return review?.interaction.status === "pending"
      ? "Review blocker recorded. Paperclip will preserve the task and record the reviewer recovery action."
      : "Review report accepted. The recorded review decision controls task completion; this report cannot override it.";
  }
  const signals = normalizePrpResultSignals(result);
  if (
    result.reportedWorkDisposition === "done" &&
    (!result.completionClaim.objectiveSatisfied ||
      result.completionClaim.criteria.some(
        (entry) => entry.status !== "satisfied",
      ) ||
      result.completionClaim.remainingWork.some(
        (entry) => entry.blocksCompletion,
      ) ||
      signals.verification.some((entry) => entry.status === "failed") ||
      signals.actionableAttentionRequests.length > 0)
  ) {
    throw new Error(
      "The done report includes unfinished work, failed verification, or an outstanding decision. Finish the work or report the concrete blocker/reviewer request. No human completion approval was created.",
    );
  }
  if (["done", "cancelled"].includes(issue.status)) {
    return `Report accepted; task is already ${issue.status}. This report will not reopen it.`;
  }
  if (issue.executionRunId && issue.executionRunId !== runId) {
    return "Report accepted; a newer run owns the task. Do not claim this report changed its status.";
  }
  const continuation = run.contextSnapshot?.executionContinuation as { objective?: unknown } | undefined;
  const objective = typeof continuation?.objective === "string"
    ? continuation.objective : [issue.title, issue.description].filter(Boolean).join("\n");
  await validateNativeDeliverableEvidence(db, { companyId: run.companyId, issueId: issue.id, runId,
    objective, semanticToolReceipts: run.resultJson?.semanticToolReceipts }, result);
  const retiredCandidates = await findAutomaticCompletionReviews(db, issue.id);
  const retiredIds = retiredCandidates.map(({ interaction }) => interaction.id);
  const [interaction, approval] = await Promise.all([
    db

View on GitHub (pinned to 3f1d897a7c)