{"record":{"id":"c8bcfbb26926c1b4","repo":"jackwener/OpenCLI","slug":"no-iframe-target-found-for-frame-frameid-targe","errorCode":null,"errorMessage":"No iframe target found for frame ${frameId}${targetUrl ? ` (${targetUrl})` : ''}. Candidates: ${candidates || 'none'}","messagePattern":"No iframe target found for frame (.+?)(.+?)\\)` : ''\\}\\. Candidates: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"extension/src/cdp.ts","lineNumber":587,"sourceCode":"  const result = await sendDebuggerCommand({ tabId }, 'Target.getTargets').catch(() => null) as\n    | { targetInfos?: Array<{ targetId?: string; id?: string; type?: string; url?: string }> }\n    | null;\n  const targets = result?.targetInfos ?? [];\n  const frameTarget = targets.find((candidate) => {\n    const candidateId = candidate.targetId || candidate.id;\n    return candidate.type === 'iframe'\n      && (\n        candidateId === frameId\n        || (!!targetUrl && candidate.url === targetUrl)\n      );\n  });\n  const targetId = frameTarget?.targetId || frameTarget?.id;\n  if (targetId) return targetId;\n  const candidates = targets\n    .filter((target) => target.type === 'iframe')\n    .map((target) => `${target.targetId || target.id || '?'} ${target.url || ''}`)\n    .join('; ');\n  throw new Error(`No iframe target found for frame ${frameId}${targetUrl ? ` (${targetUrl})` : ''}. Candidates: ${candidates || 'none'}`);\n}\n\nexport async function sendCommandInFrameTarget(\n  tabId: number,\n  frameId: string,\n  method: string,\n  params: Record<string, unknown> = {},\n  aggressiveRetry: boolean = false,\n  timeoutMs: number = CDP_COMMAND_TIMEOUT_MS,\n  targetUrl?: string,\n): Promise<unknown> {\n  const targetId = await ensureFrameTarget(tabId, frameId, aggressiveRetry, targetUrl);\n  const target = { targetId } as chrome.debugger.Debuggee;\n  return sendDebuggerCommand(target, method, params, timeoutMs);\n}\n\nexport async function insertText(\n  tabId: number,","sourceCodeStart":569,"sourceCodeEnd":605,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/extension/src/cdp.ts#L569-L605","documentation":"This error is thrown by resolveFrameTargetId in extension/src/cdp.ts:587 when ensureFrameTarget cannot find a CDP iframe target matching the requested frameId (or targetUrl) among the tab's Target.getTargets() results. The extension auto-attaches to iframes via Target.setAutoAttach with an iframe filter, then looks up the matching out-of-process iframe target to route frame-scoped CDP commands. If no candidate matches, it throws and includes all discovered iframe candidates in the message to aid debugging.","triggerScenarios":"Calling sendCommandInFrameTarget or evaluateInFrame with a frameId that has no matching out-of-process iframe target: the frame is same-process (no separate target created), the frame navigated/reloaded and its target id changed, Target.getTargets returned before the iframe target was registered, the frameId passed is a Chrome frameTree frameId rather than a CDP iframe targetId, or the page has no iframes at all.","commonSituations":"Automating a page whose iframes are same-origin (Chrome keeps them in-process, so no iframe target exists); racing a just-inserted iframe before auto-attach fires; stale cached frame references after SPA navigation; passing the wrong id field (e.g. webFrameTree frameId vs targetId); headless or restricted environments where Target.setDiscoverTargets fails silently.","solutions":["Pass the frame's exact URL as targetUrl so resolveFrameTargetId can match by URL, or re-resolve the frameId from Page.getFrameTree immediately before the call.","Retry after a short delay to let Target.setAutoAttach register the iframe target (this is what aggressiveRetry is for).","Verify with Target.getTargets (or the 'none' in the message) whether any iframe targets exist; if none, evaluate in the main tab context instead.","If the call came from evaluateInFrame, ensure Runtime.enable was issued so execution-context tracking populated tabFrameContexts; clear stale context cache and retry.","Check Chrome version/platform — some embedders (e.g. Electron, older Chromium) do not create OOPIF targets for same-site iframes."],"exampleFix":"// before\nawait sendCommandInFrameTarget(tabId, frameId, 'Runtime.evaluate', { expression });\n// after\nconst tree = await getFrameTree(tabId);\nconst frameUrl = tree?.frame?.childFrames?.find(f => f.frame.id === frameId)?.frame.url;\nawait sendCommandInFrameTarget(tabId, frameId, 'Runtime.evaluate', { expression }, true /* aggressiveRetry */, undefined, frameUrl);","handlingStrategy":"retry","validationCode":"const tree = await cdp.getFrameTree(tabId);\nconst hasIframeTargets = (await cdp.getTargetInfos(tabId)).some(t => t.type === 'iframe');\nif (!hasIframeTargets) throw new SkipError('page has no OOPIF iframe targets; evaluate in main frame');","typeGuard":"function isIframeTarget(t: { type?: string; targetId?: string; id?: string }): t is { type: 'iframe'; targetId: string } {\n  return t.type === 'iframe' && typeof (t.targetId || t.id) === 'string';\n}","tryCatchPattern":"try {\n  await sendCommandInFrameTarget(tabId, frameId, method, params, true /* aggressiveRetry */, timeoutMs, frameUrl);\n} catch (err) {\n  if (err instanceof Error && /No iframe target found/.test(err.message)) {\n    await sleep(250); // let Target.setAutoAttach register the OOPIF target\n    return sendCommandInFrameTarget(tabId, frameId, method, params, true, timeoutMs, frameUrl);\n  }\n  throw err;\n}","preventionTips":["Always pass the frame's current URL (from Page.getFrameTree) as targetUrl to enable URL-based matching.","Use aggressiveRetry for freshly created/navigated iframes so auto-attach has time to register the target.","Distinguish frameTree frameIds from CDP iframe targetIds; don't pass one where the other is expected.","Log the Candidates list from the error to detect systematic absence of OOPIF targets (same-process iframes)."],"tags":["cdp","iframe","chrome-extension","frame-target"],"backgroundTag":"cdp-iframe-target-not-found","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}