diff --git a/ui/src/api/assets.ts b/ui/src/api/assets.ts index b895ae0b..25555a6a 100644 --- a/ui/src/api/assets.ts +++ b/ui/src/api/assets.ts @@ -2,9 +2,16 @@ import type { AssetImage } from "@paperclip/shared"; import { api } from "./client"; export const assetsApi = { - uploadImage: (companyId: string, file: File, namespace?: string) => { + uploadImage: async (companyId: string, file: File, namespace?: string) => { + // Read file data into memory eagerly so the fetch body is self-contained. + // Clipboard-paste File objects reference transient data that the browser may + // discard after the paste-event handler returns, causing ERR_ACCESS_DENIED + // when fetch() later tries to stream the FormData body. + const buffer = await file.arrayBuffer(); + const safeFile = new File([buffer], file.name, { type: file.type }); + const form = new FormData(); - form.append("file", file); + form.append("file", safeFile); if (namespace && namespace.trim().length > 0) { form.append("namespace", namespace.trim()); } diff --git a/ui/src/components/NewIssueDialog.tsx b/ui/src/components/NewIssueDialog.tsx index 1aead1e9..1649d882 100644 --- a/ui/src/components/NewIssueDialog.tsx +++ b/ui/src/components/NewIssueDialog.tsx @@ -237,6 +237,7 @@ export function NewIssueDialog() { >