{"record":{"id":"ec62481fa8337e98","repo":"nexu-io/open-design","slug":"the-host-returned-an-invalid-confirmation","errorCode":null,"errorMessage":"The host returned an invalid confirmation.","messagePattern":"The host returned an invalid confirmation\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"apps/daemon/src/mcp-apps/brief-resource.ts","lineNumber":467,"sourceCode":"            status.textContent = copy().contextFailed;\n            scheduleSizeChanged();\n          });\n        });\n\n        form.addEventListener(\"submit\", async (event) => {\n          event.preventDefault();\n          if (phase !== \"ready\" || !draft || !form.reportValidity()) return;\n          applyPhase(\"confirming\");\n          let payload;\n          try {\n            const result = await callConfirm({\n              briefDraftId: draft.briefDraftId,\n              nonce: draft.nonce,\n              answers: selections(),\n              locale: effectiveLocale(),\n            });\n            payload = result && (result.structuredContent || (result.result && result.result.structuredContent) || result);\n            if (!payload || !payload.briefConfirmationId) throw new Error(copy().invalidConfirmation);\n          } catch (error) {\n            applyPhase(\n              \"ready\",\n              publicErrorMessage(error, copy().confirmFailed),\n            );\n            return;\n          }\n          confirmedPayload = payload;\n          applyPhase(\"confirmed_publishing\");\n          try {\n            const contextCleared = await publishConfirmation(confirmedPayload);\n            applyPhase(\n              \"delivered\",\n              contextCleared ? undefined : copy().deliveredContextCleanupFailed,\n            );\n          } catch {\n            applyPhase(\"confirmed_publish_failed\");\n          }","sourceCodeStart":449,"sourceCodeEnd":485,"githubUrl":"https://github.com/nexu-io/open-design/blob/5be4028344c2eb4c667c5a97bda8f750c5597ef7/apps/daemon/src/mcp-apps/brief-resource.ts#L449-L485","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the Open Design daemon logs for the confirm_brief call — a validation error there is the usual cause.","Ensure the daemon is the version that matches the brief UI (both should ship together).","Re-open the brief to get a fresh briefDraftId/nonce (the draft may have expired) and confirm again.","If you control the host, verify it forwards structuredContent from the tools/call result unchanged."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Validate the confirm_brief tool result shape before treating it as a confirmed payload.\nfunction isBriefConfirmation(result: unknown): result is { briefConfirmationId: string } {\n  if (!result || typeof result !== 'object') return false;\n  const r = result as Record<string, unknown>;\n  const payload = r.structuredContent ?? (r.result && r.result.structuredContent) ?? r;\n  return !!payload && typeof payload.briefConfirmationId === 'string';\n}\n\nconst result = await callConfirm(args);\nif (!isBriefConfirmation(result)) {\n  // Show a user-facing error; do not advance to publish.\n}","typeGuard":"function isBriefConfirmationPayload(value: unknown): value is { briefConfirmationId: string; summary?: string } {\n  if (!value || typeof value !== 'object') return false;\n  const v = value as Record<string, unknown>;\n  return typeof v.briefConfirmationId === 'string';\n}","tryCatchPattern":"// In-source: the submit handler already wraps callConfirm in try/catch and re-applies 'ready'.\ntry {\n  const result = await callConfirm(args);\n  payload = result && (result.structuredContent || (result.result && result.result.structuredContent) || result);\n  if (!payload || !payload.briefConfirmationId) throw new Error(copy().invalidConfirmation);\n} catch (error) {\n  applyPhase('ready', publicErrorMessage(error, copy().confirmFailed));\n  return;\n}","preventionTips":["Keep the brief UI and the daemon in lockstep so confirm_brief always returns briefConfirmationId.","Re-open the brief to refresh briefDraftId/nonce if confirmation keeps failing (the draft may have expired).","If you proxy tool results, forward structuredContent unchanged."],"tags":["mcp-apps","brief","browser","validation","confirmation","host-capability"],"backgroundTag":null,"analyzedSha":"5be4028344c2eb4c667c5a97bda8f750c5597ef7","analyzedAt":"2026-08-12T12:03:58.812Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}