nexu-io/open-design · error · Error

The host returned an invalid confirmation.

Error message

The host returned an invalid confirmation.

What it means

Browser-side error thrown during form submission when callConfirm() returned a result that does not contain a `briefConfirmationId`. The confirm_brief tool is expected to return structuredContent (or a nested result.result.structuredContent) with at least `briefConfirmationId`; absence means the host/daemon returned a malformed or incomplete confirmation payload. This is treated as a confirmation failure and the form reverts to the ready phase with an error message.

Source

Thrown at apps/daemon/src/mcp-apps/brief-resource.ts:467

            status.textContent = copy().contextFailed;
            scheduleSizeChanged();
          });
        });

        form.addEventListener("submit", async (event) => {
          event.preventDefault();
          if (phase !== "ready" || !draft || !form.reportValidity()) return;
          applyPhase("confirming");
          let payload;
          try {
            const result = await callConfirm({
              briefDraftId: draft.briefDraftId,
              nonce: draft.nonce,
              answers: selections(),
              locale: effectiveLocale(),
            });
            payload = result && (result.structuredContent || (result.result && result.result.structuredContent) || result);
            if (!payload || !payload.briefConfirmationId) throw new Error(copy().invalidConfirmation);
          } catch (error) {
            applyPhase(
              "ready",
              publicErrorMessage(error, copy().confirmFailed),
            );
            return;
          }
          confirmedPayload = payload;
          applyPhase("confirmed_publishing");
          try {
            const contextCleared = await publishConfirmation(confirmedPayload);
            applyPhase(
              "delivered",
              contextCleared ? undefined : copy().deliveredContextCleanupFailed,
            );
          } catch {
            applyPhase("confirmed_publish_failed");
          }

View on GitHub (pinned to 5be4028344)

Solutions

  1. Check the Open Design daemon logs for the confirm_brief call — a validation error there is the usual cause.
  2. Ensure the daemon is the version that matches the brief UI (both should ship together).
  3. Re-open the brief to get a fresh briefDraftId/nonce (the draft may have expired) and confirm again.
  4. If you control the host, verify it forwards structuredContent from the tools/call result unchanged.
Defensive patterns

Strategy: validation

Validate before calling

// Validate the confirm_brief tool result shape before treating it as a confirmed payload.
function isBriefConfirmation(result: unknown): result is { briefConfirmationId: string } {
  if (!result || typeof result !== 'object') return false;
  const r = result as Record<string, unknown>;
  const payload = r.structuredContent ?? (r.result && r.result.structuredContent) ?? r;
  return !!payload && typeof payload.briefConfirmationId === 'string';
}

const result = await callConfirm(args);
if (!isBriefConfirmation(result)) {
  // Show a user-facing error; do not advance to publish.
}

Type guard

function isBriefConfirmationPayload(value: unknown): value is { briefConfirmationId: string; summary?: string } {
  if (!value || typeof value !== 'object') return false;
  const v = value as Record<string, unknown>;
  return typeof v.briefConfirmationId === 'string';
}

Try / catch

// In-source: the submit handler already wraps callConfirm in try/catch and re-applies 'ready'.
try {
  const result = await callConfirm(args);
  payload = result && (result.structuredContent || (result.result && result.result.structuredContent) || result);
  if (!payload || !payload.briefConfirmationId) throw new Error(copy().invalidConfirmation);
} catch (error) {
  applyPhase('ready', publicErrorMessage(error, copy().confirmFailed));
  return;
}

Prevention

When it happens

Trigger: The confirm_brief tool returned `{}` or a result without structuredContent; the daemon's confirm_brief handler errored partway and returned a partial payload; a nonce/briefDraftId mismatch caused the daemon to reject without setting briefConfirmationId; the host rewrote the result envelope and dropped structuredContent.

Common situations: Daemon version skew (older daemon that does not mint briefConfirmationId); the brief draft expired before confirmation (nonce no longer valid); a proxy/host stripped structuredContent from the tool result; bug in the confirm_brief handler returning early.

Related errors


AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12). Data as JSON: /api/errors/ec62481fa8337e98. Report an issue: GitHub.