{"record":{"id":"11e2fb915e63fd43","repo":"different-ai/openwork","slug":"could-not-upload-brand-images-response-status","errorCode":null,"errorMessage":"Could not upload brand images (${response.status}).","messagePattern":"Could not upload brand images \\((.+?)\\)\\.","errorType":"http","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"ee/apps/den-web/app/(den)/dashboard/_components/brand-appearance-screen.tsx","lineNumber":248,"sourceCode":"  async function handleSave(event: React.FormEvent<HTMLFormElement>) {\n    event.preventDefault();\n    setPageError(null);\n    setPageSuccess(null);\n\n    if (!canManageBrandAppearance) {\n      setPageError(\"Only workspace owners and super-admins can change brand appearance.\");\n      return;\n    }\n\n    try {\n      if (logoDraft || iconDraft) {\n        setUploadBusy(true);\n        await runReauthableAction(\"upload-brand-assets\", async () => {\n          const body = new FormData();\n          if (logoDraft) body.set(\"logo\", logoDraft.file);\n          if (iconDraft) body.set(\"icon\", iconDraft.file);\n          const { response, payload } = await requestJson(\"/v1/org/brand-assets\", { method: \"POST\", body }, 30000);\n          if (!response.ok) throw getRequestError(payload, response, `Could not upload brand images (${response.status}).`);\n        });\n      }\n\n      await updateOrganizationSettings({\n        brandAppName: appNameDraft.trim() || null,\n        brandAccentColor: accentColorDraft || null,\n        ...(logoClearPending ? { brandLogoUrl: null } : {}),\n        ...(iconClearPending ? { brandIconUrl: null } : {}),\n      });\n      setPageSuccess(\"Brand appearance updated.\");\n    } catch (error) {\n      setPageError(error instanceof Error ? error.message : \"Could not update brand appearance.\");\n    } finally {\n      setUploadBusy(false);\n    }\n  }\n\n  const saveBusy = uploadBusy || mutationBusy === \"update-organization-settings\";","sourceCodeStart":230,"sourceCodeEnd":266,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-web/app/(den)/dashboard/_components/brand-appearance-screen.tsx#L230-L266","documentation":"Thrown by handleSave in the brand appearance screen when POST /v1/org/brand-assets (multipart FormData with logo/icon files) returns a non-OK status. getRequestError prefers the server's error message, reauth payload becoming ReauthRequiredError. It means the brand image upload was rejected by the server.","triggerScenarios":"Upload rejected: file too large (413), unsupported MIME/image format (415/400), user lacks org admin permission (403), session expired (401), reauth required, or storage failure (5xx). 30s timeout applies.","commonSituations":"Uploading an oversized PNG/SVG logo; uploading a non-image file; non-admin member editing brand settings; self-hosted storage (S3/blob) misconfigured; long upload on slow connection exceeding the 30s timeout then surfacing as error status.","solutions":["Check the surfaced server message for size/format specifics.","Compress or resize the logo/icon and use a supported format (PNG/SVG/JPEG) under the server's size limit.","Retry as an org admin; permissions are required for brand asset writes.","Handle reauth-required errors by re-authenticating.","If 5xx, verify server-side asset storage configuration and logs."],"exampleFix":"// before\nif (!response.ok) throw getRequestError(payload, response, `Could not upload brand images (${response.status}).`);\n// after\nif (!response.ok) {\n  const err = getRequestError(payload, response, `Could not upload brand images (${response.status}).`);\n  if (response.status === 413) throw new Error(\"Image too large - please use a file under the size limit.\");\n  throw err;\n}","handlingStrategy":"validation","validationCode":"const MAX_BYTES = 5 * 1024 * 1024;\nconst ALLOWED = [\"image/png\", \"image/jpeg\", \"image/svg+xml\"];\nfunction fileOk(f: File) { return ALLOWED.includes(f.type) && f.size <= MAX_BYTES; }\nif ((logoDraft && !fileOk(logoDraft.file)) || (iconDraft && !fileOk(iconDraft.file))) {\n  setUploadError(\"Images must be PNG/JPEG/SVG under 5MB.\"); return;\n}","typeGuard":"function isImageFile(f: File): boolean { return f.type.startsWith(\"image/\"); }","tryCatchPattern":"try {\n  await runReauthableAction(\"upload-brand-assets\", upload);\n} catch (error) {\n  if (isReauthRequiredError(error)) { promptReauth(); return; }\n  setUploadError(error instanceof Error ? error.message : \"Could not upload brand images.\");\n}","preventionTips":["Validate file type and size client-side before building FormData","Only allow org admins to reach the brand settings screen","Compress large logos before upload","Use a timeout generous enough (30s) for slow connections and surface progress"],"tags":["http","upload","file-validation","network"],"backgroundTag":"asset-upload-rejected","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}