From 4b7fdaea01bfa2a73616017ea32d6b33cdbf3330 Mon Sep 17 00:00:00 2001 From: Forgotten Date: Mon, 23 Feb 2026 15:21:04 -0600 Subject: [PATCH] fix: resolve image upload ERR_ACCESS_DENIED and dialog a11y warning Eagerly read file data into memory via arrayBuffer() before constructing FormData for the upload fetch. Clipboard-paste File objects from the MDX editor reference transient browser data that may be discarded after the paste event handler returns; streaming that stale reference in the fetch body causes net::ERR_ACCESS_DENIED. Reading into an ArrayBuffer first makes the FormData self-contained. Also suppress the Radix UI "Missing Description" console warning on the NewIssueDialog by setting aria-describedby={undefined}. Co-Authored-By: Claude Opus 4.6 --- ui/src/api/assets.ts | 11 +++++++++-- ui/src/components/NewIssueDialog.tsx | 1 + 2 files changed, 10 insertions(+), 2 deletions(-) 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() { >