{"record":{"id":"07bdcacc4775cd6d","repo":"tldraw/tldraw","slug":"failed-to-copy","errorCode":null,"errorMessage":"Failed to copy","messagePattern":"Failed to copy","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"packages/tldraw/src/lib/utils/export/copyAs.ts","lineNumber":72,"sourceCode":"\t\tconst { blobPromise, mimeType } = exportToImagePromiseForClipboard(editor, ids, imageOpts)\n\n\t\tconst types: Record<string, Promise<Blob>> = { [mimeType]: blobPromise }\n\t\tconst additionalMimeType = getAdditionalClipboardWriteType(opts.format)\n\t\tif (additionalMimeType && doesClipboardSupportType(additionalMimeType)) {\n\t\t\ttypes[additionalMimeType] = blobPromise.then((blob) =>\n\t\t\t\tFileHelpers.rewriteMimeType(blob, additionalMimeType)\n\t\t\t)\n\t\t}\n\n\t\treturn clipboardWrite(types)\n\t}\n\n\tswitch (opts.format) {\n\t\tcase 'svg': {\n\t\t\treturn fallbackWriteTextAsync(async () => {\n\t\t\t\tconst result = await editor.getSvgString(ids, imageOpts)\n\n\t\t\t\tif (!result) throw new Error('Failed to copy')\n\t\t\t\treturn result.svg\n\t\t\t})\n\t\t}\n\n\t\tcase 'png':\n\t\t\tthrow new Error('Copy not supported')\n\t\tdefault:\n\t\t\texhaustiveSwitchError(opts.format)\n\t}\n}\n\nasync function fallbackWriteTextAsync(getText: () => Promise<string>) {\n\tawait navigator.clipboard?.writeText?.(await getText())\n}\n","sourceCodeStart":54,"sourceCodeEnd":87,"githubUrl":"https://github.com/tldraw/tldraw/blob/b31086b44731a7d1d9d46be4163ac8ef7417321d/packages/tldraw/src/lib/utils/export/copyAs.ts#L54-L87","documentation":"Thrown on the SVG fallback copy path in copyAs when navigator.clipboard.write is unavailable (so the code falls into the format switch) and editor.getSvgString(ids, imageOpts) returns null. A null result means the editor could not produce an SVG for the given selection, so there is nothing to write to the clipboard and the copy aborts.","triggerScenarios":"Calling copyAs(editor, ids, { format: 'svg' }) in a browser without async ClipboardItem.write support (falls into the switch), with an ids list that is empty or contains only shapes whose ShapeUtil does not implement toSvg (or shapes that have no renderable geometry), so getSvgString resolves to null.","commonSituations":"User triggers copy-as-SVG with nothing selected; the selection contains only shapes (e.g. a custom shape) whose util has no getSvg/toSvg method; assets referenced by the shapes failed to load so SVG export bails; running in a browser/iframe where clipboard.write is missing.","solutions":["Guard the call: only copy when ids.length > 0 and editor.canExportShapes(ids) (or check getSvgString result) is truthy.","Ensure every custom ShapeUtil implements toSvg / the SVG export path.","If clipboard.write is available, prefer it (it produces a proper image/svg+xml ClipboardItem) instead of the text fallback.","Show a user-facing message when getSvgString returns null rather than letting the throw surface."],"exampleFix":"// before: unconditional copy\nawait copyAs(editor, ids, { format: 'svg' })\n\n// after: guard before copying\nif (ids.length === 0) return\nconst svg = await editor.getSvgString(ids, { format: 'svg' })\nif (!svg) {\n  showToast('Nothing to copy')\n  return\n}\nawait copyAs(editor, ids, { format: 'svg' })","handlingStrategy":"validation","validationCode":"// Pre-flight: confirm SVG export will succeed before copying.\nif (ids.length === 0) return\nconst preview = await editor.getSvgString(ids, { format: 'svg' })\nif (!preview) {\n  notifyUser('Nothing to copy as SVG.')\n  return\n}\nawait copyAs(editor, ids, { format: 'svg' })","typeGuard":"function canExportSvg(editor: Editor, ids: TLShapeId[]): boolean {\n  return ids.length > 0 && ids.every(id => {\n    const util = editor.getShapeUtil(editor.getShape(id)!.type)\n    return typeof util.toSvg === 'function'\n  })\n}","tryCatchPattern":"try {\n  await copyAs(editor, ids, { format: 'svg' })\n} catch (e: any) {\n  if (/Failed to copy/i.test(e.message)) {\n    notifyUser('Could not copy the selection as SVG.')\n  } else throw e\n}","preventionTips":["Disable the copy-as-SVG action when the selection is empty.","Implement toSvg on every custom ShapeUtil you author.","Prefer the clipboard.write path (async ClipboardItem) when available."],"tags":["clipboard","export","svg","browser"],"backgroundTag":null,"analyzedSha":"b31086b44731a7d1d9d46be4163ac8ef7417321d","analyzedAt":"2026-08-12T17:05:39.947Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}