{"record":{"id":"f5a29af185f11949","repo":"pbakaus/impeccable","slug":"copy-failed","errorCode":null,"errorMessage":"Copy failed","messagePattern":"Copy failed","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"extension/devtools/panel.js","lineNumber":359,"sourceCode":"  lines.push(`Suggested Impeccable skill(s) to fix: ${fixSkillFor(finding.type)}`);\n  return lines.join('\\n');\n}\n\nasync function copyToClipboard(text, btn) {\n  if (text instanceof Promise) text = await text;\n  try {\n    await navigator.clipboard.writeText(text);\n    if (btn) {\n      const orig = btn.title;\n      btn.title = 'Copied!';\n      btn.classList.add('copied');\n      setTimeout(() => {\n        btn.title = orig;\n        btn.classList.remove('copied');\n      }, 1200);\n    }\n  } catch (err) {\n    console.warn('Copy failed', err);\n  }\n}\n\nbtnCopyAll.addEventListener('click', () => {\n  copyToClipboard(formatFindingsForCopy(currentFindings), btnCopyAll);\n});\n\n// Delegated hover tracking on the findings container.\n// Reliably handles cursor moving between items, into children, or out of the panel.\nlet currentHoverSelector = null;\nfunction setHoveredItem(selector) {\n  if (selector === currentHoverSelector) return;\n  currentHoverSelector = selector;\n  if (selector) {\n    postToPort({ action: 'highlight', selector });\n  } else {\n    postToPort({ action: 'unhighlight' });\n  }","sourceCodeStart":341,"sourceCodeEnd":377,"githubUrl":"https://github.com/pbakaus/impeccable/blob/f88b2837a7d7c3182e46307bbbb091a1ed547571/extension/devtools/panel.js#L341-L377","documentation":"The DevTools panel's copyToClipboard wraps navigator.clipboard.writeText in try/catch to copy formatted findings. If the promise rejects — clipboard-write denied by permissions policy, document not focused, API unavailable in the panel context — it logs 'Copy failed' with the error and leaves the clipboard untouched; the button briefly shows the copied state only on success paths controlled elsewhere.","triggerScenarios":"Clicking Copy when the devtools panel iframe is not the focused document; a permissions policy that withlays clipboard-write from the panel; headless/automated contexts where the Clipboard API is disabled.","commonSituations":"Focus sits in the inspected page or another window when the click lands; enterprise browser policies disabling clipboard API; older Chrome where writeText requires a tightly-scoped user gesture.","solutions":["Click directly on the Copy button so the user gesture is unambiguous, then retry","Select the findings text in the panel and use Cmd/Ctrl+C as the manual fallback","If building similar UI, fall back to a hidden textarea + document.execCommand('copy') on rejection"],"exampleFix":"// before\nawait navigator.clipboard.writeText(text);\n// after\ntry { await navigator.clipboard.writeText(text); }\ncatch {\n  const ta = document.createElement('textarea');\n  ta.value = text; document.body.appendChild(ta); ta.select();\n  document.execCommand('copy'); ta.remove();\n}","handlingStrategy":"fallback","validationCode":"if (!navigator.clipboard?.writeText) { useLegacyCopy(text); return; }","typeGuard":null,"tryCatchPattern":"try {\n  await navigator.clipboard.writeText(text);\n} catch (err) {\n  console.warn('Copy failed', err);\n  const ta = document.createElement('textarea');\n  ta.value = text; ta.style.position = 'fixed'; ta.style.opacity = '0';\n  document.body.appendChild(ta); ta.select();\n  document.execCommand('copy'); ta.remove();\n}","preventionTips":["Only invoke copy from a real click handler so the user gesture is fresh","Refocus the panel/window before retrying after a failure","Keep a legacy execCommand path for locked-down environments"],"tags":["clipboard","devtools-panel","permissions","user-gesture"],"backgroundTag":"clipboard-write-denied","analyzedSha":"f88b2837a7d7c3182e46307bbbb091a1ed547571","analyzedAt":"2026-08-18T04:58:36.608Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}