{"record":{"id":"26ff53c9e7826150","repo":"different-ai/openwork","slug":"mcp-app-sandbox-document-error","errorCode":"MCP_APP_SANDBOX_DOCUMENT_ERROR","errorMessage":"The sandbox iframe reported a document load error.","messagePattern":"The sandbox iframe reported a document load error\\.","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"apps/server/src/mcp-app-sandbox.ts","lineNumber":98,"sourceCode":"  const inner = document.createElement(\"iframe\");\n  inner.title = \"MCP App view\";\n  inner.style.cssText = \"display:block;width:100%;height:100%;border:0;background:transparent\";\n  inner.setAttribute(\"sandbox\", \"allow-scripts allow-same-origin\");\n  let resourceAssigned = false;\n  inner.addEventListener(\"load\", () => {\n    if (!resourceAssigned) return;\n    let readyState = null;\n    let hasHtmlRoot = null;\n    let scriptCount = null;\n    try {\n      readyState = inner.contentDocument?.readyState || null;\n      hasHtmlRoot = Boolean(inner.contentDocument?.documentElement);\n      scriptCount = inner.contentDocument?.scripts.length ?? null;\n    } catch {}\n    notifyHost(\"ui/notifications/sandbox-resource-loaded\", { readyState, hasHtmlRoot, scriptCount });\n  });\n  inner.addEventListener(\"error\", () => {\n    if (resourceAssigned) notifyHost(\"ui/notifications/sandbox-diagnostic\", { code: \"MCP_APP_SANDBOX_DOCUMENT_ERROR\", message: \"The sandbox iframe reported a document load error.\" });\n  });\n  document.body.appendChild(inner);\n  window.addEventListener(\"message\", (event) => {\n    if (event.source === window.parent) {\n      if (event.origin !== hostOrigin) return;\n      if (event.data?.method === \"ui/notifications/sandbox-resource-ready\") {\n        const html = event.data?.params?.html;\n        const sandbox = event.data?.params?.sandbox;\n        if (typeof sandbox === \"string\" && /^(?:allow-scripts|allow-same-origin|\\s)+$/.test(sandbox)) inner.setAttribute(\"sandbox\", sandbox);\n        if (typeof html !== \"string\") {\n          notifyHost(\"ui/notifications/sandbox-diagnostic\", { code: \"MCP_APP_SANDBOX_RESOURCE_INVALID\", message: \"The sandbox received an invalid HTML resource payload.\" });\n          return;\n        }\n        try {\n          resourceAssigned = true;\n          inner.srcdoc = html;\n          notifyHost(\"ui/notifications/sandbox-resource-accepted\");\n        } catch {","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/apps/server/src/mcp-app-sandbox.ts#L80-L116","documentation":"The MCP app sandbox iframe fired its native `error` event after an HTML resource had already been assigned (resourceAssigned === true). The sandbox notifies the host via a sandbox-diagnostic with code MCP_APP_SANDBOX_DOCUMENT_ERROR, meaning the srcdoc document failed at load time (e.g. blocked script, CSP violation, malformed HTML triggering a resource error).","triggerScenarios":"Setting inner.srcdoc to HTML whose load raises an iframe error event — scripts blocked by the sandbox attribute, CSP refusing inline scripts, or the document referencing resources that fail hard enough to error the frame.","commonSituations":"Sandbox attr lacking allow-scripts while the HTML includes <script>; server CSP (frame-src/CSP headers) conflicting with srcdoc; app HTML expecting same-origin assets unavailable in the sandboxed origin.","solutions":["Check the sandbox attribute includes allow-scripts when the app HTML executes JavaScript.","Open the iframe/webview devtools console for the underlying CSP or script error details.","Remove or inline external resource references that violate the sandbox's opaque origin.","If the error is benign (e.g. favicon 404 surfacing as an error), filter it in the host's sandbox-diagnostic handler."],"exampleFix":"// before\ninner.setAttribute(\"sandbox\", \"allow-same-origin\");\n// after\ninner.setAttribute(\"sandbox\", \"allow-scripts allow-same-origin\");","handlingStrategy":"validation","validationCode":"const needsScripts = /<script/i.test(appHtml);\nconst sandboxAttr = inner.getAttribute(\"sandbox\") ?? \"\";\nif (needsScripts && !sandboxAttr.includes(\"allow-scripts\")) {\n  inner.setAttribute(\"sandbox\", (sandboxAttr + \" allow-scripts\").trim());\n}","typeGuard":null,"tryCatchPattern":"window.addEventListener(\"message\", (e) => {\n  if (e.data?.code === \"MCP_APP_SANDBOX_DOCUMENT_ERROR\") {\n    console.warn(\"sandbox doc load error — check iframe console/CSP\");\n  }\n});","preventionTips":["Match the sandbox attribute to the app's needs (allow-scripts for JS apps)","Test app HTML inside a sandboxed iframe in CI, not only top-level","Keep inline scripts/resources self-contained for the opaque origin"],"tags":["iframe","sandbox","csp","mcp-apps"],"backgroundTag":"iframe-load-error","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}