paperclipai/paperclip · error · Error

Review unavailable

Error message

Review unavailable

What it means

TaskChatComposer's `reviewUncertainSubmission` throws this when invoked but the `onReviewConversation` prop is undefined. Like IssueChatThread's equivalent, the composer cannot trigger the review conversation itself; the catch sets `reviewError` to show an inline error near the uncertain submission card.

Solutions

  1. Provide `onReviewConversation` whenever uncertain submissions can render in TaskChatComposer.
  2. Hide the review affordance (or the uncertain card) when the prop is absent.
  3. Trace the parent component to confirm the conditional passing of the callback is correct.

Example fix

// before
<TaskChatComposer onSubmit={submit} uncertainSubmission={u} />
// after
<TaskChatComposer onSubmit={submit} uncertainSubmission={u} onReviewConversation={review} />
Defensive patterns

Strategy: try-catch

Validate before calling

if (typeof onReviewConversation !== 'function') return; // hide review affordance

Type guard

const isReviewable = (p: unknown): p is () => Promise<void> => typeof p === 'function';

Try / catch

try { await onReviewConversation(); } catch { setReviewError(true); }

Prevention

When it happens

Trigger: An uncertain submission is displayed and the user clicks review, while the parent rendered TaskChatComposer without `onReviewConversation` (or passed it conditionally and the condition was false).

Common situations: Parent pages that wire submission but not the review callback; feature-flagged review flow where the flag off leaves the prop undefined while the card still renders.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at ui/src/components/task-chat/TaskChatComposer.tsx:1072

  useEffect(() => {
    if (!uncertainSubmission || !confirmedSubmissionIds?.has(uncertainSubmission.attemptId)) return;
    const nextDraft = uncertainSubmission.nextDraftOffset === undefined
      ? "" : bodyRef.current.slice(uncertainSubmission.nextDraftOffset);
    if (draftKey) settleDraftSubmission(draftKey, uncertainSubmission.attemptId, nextDraft);
    setUncertainSubmission(null);
    bodyRef.current = nextDraft;
    setBody(nextDraft);
    const submittedIds = uncertainSubmission.submittedAttachmentIds;
    setAttachments(current => submittedIds
      ? current.filter(item => !item.attachmentId || !submittedIds.includes(item.attachmentId))
      : []);
  }, [confirmedSubmissionIds, draftKey, uncertainSubmission]);

  async function reviewUncertainSubmission() {
    if (!uncertainSubmission) return;
    setReviewError(false);
    try {
      if (!onReviewConversation) throw new Error("Review unavailable");
      await onReviewConversation();
      if (mountedTaskKey.current !== draftKey) return;
      const reviewed = { ...uncertainSubmission, reviewed: true };
      setUncertainSubmission(reviewed);
      if (
        draftKey &&
        loadDraftSubmission(draftKey)?.attemptId === reviewed.attemptId
      )
        saveDraftSubmission(draftKey, reviewed);
    } catch {
      setReviewError(true);
    }
  }

  function discardUncertainDraft() {
    if (!uncertainSubmission?.reviewed) return;
    if (draftKey) clearDraft(draftKey, uncertainSubmission.attemptId);
    bodyRef.current = "";

View on GitHub (pinned to 3f1d897a7c)