{"record":{"id":"4c033f1463771f9c","repo":"different-ai/openwork","slug":"use-a-png-or-jpeg-image","errorCode":null,"errorMessage":"Use a PNG or JPEG image.","messagePattern":"Use a PNG or JPEG image\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"ee/apps/den-web/app/(den)/dashboard/_components/brand-appearance-screen.tsx","lineNumber":32,"sourceCode":"import { DenCard } from \"../../_components/ui/card\";\nimport { DenInput } from \"../../_components/ui/input\";\nimport { DenNotice } from \"../../_components/ui/notice\";\nimport { useOrgDashboard } from \"../_providers/org-dashboard-provider\";\nimport { EnterprisePlanNotice } from \"./enterprise-plan-notice\";\n\nconst BRAND_ASSET_MAX_BYTES = 2 * 1024 * 1024;\n\ntype BrandAssetKind = \"logo\" | \"icon\";\n\ntype BrandAssetDraft = {\n  file: File;\n  previewUrl: string;\n  width: number;\n  height: number;\n};\n\nasync function createBrandAssetDraft(file: File, kind: BrandAssetKind): Promise<BrandAssetDraft> {\n  if (file.type !== \"image/png\" && file.type !== \"image/jpeg\") throw new Error(\"Use a PNG or JPEG image.\");\n  if (file.size > BRAND_ASSET_MAX_BYTES) throw new Error(\"Use an image under 2 MB.\");\n\n  let image: ImageBitmap;\n  try {\n    image = await createImageBitmap(file);\n  } catch {\n    throw new Error(\"OpenWork could not decode that image.\");\n  }\n\n  const { width, height } = image;\n  image.close();\n  if (width > 4096 || height > 4096) throw new Error(\"Use an image no larger than 4096×4096 pixels.\");\n  if (kind === \"icon\") {\n    if (width < 64 || height < 64) throw new Error(\"Use a square icon at least 64×64 pixels.\");\n    if (width !== height) throw new Error(\"Use a square image for the app icon.\");\n  } else {\n    const aspectRatio = width / height;\n    if (width < 128 || height < 32) throw new Error(\"Use a wordmark at least 128×32 pixels.\");","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-web/app/(den)/dashboard/_components/brand-appearance-screen.tsx#L14-L50","documentation":"createBrandAssetDraft validates brand assets before decoding them; the very first check rejects any File whose MIME type is not image/png or image/jpeg. This guards the image pipeline (createImageBitmap, dimension checks, upload) which only supports these two formats.","triggerScenarios":"Uploading an app icon or wordmark file with MIME type image/webp, image/gif, image/svg+xml, image/avif, image/tiff, or any non-image type (e.g. a .png file renamed from a GIF whose stored type is image/gif, or type \"\" for unknown extensions).","commonSituations":"Designer hands over a WebP or SVG export; a file saved with a .png extension is actually GIF/WebP data so the browser reports the real MIME type; drag-and-drop of a PDF or HEIC screenshot from iOS; older Safari reporting empty file.type.","solutions":["Convert the image to PNG (best for icons) or JPEG in an image editor and re-upload.","Never rely on file extension; check the reported MIME type in devtools — the guard uses file.type, the browser-sniffed type.","Export as PNG from Figma/Sketch/Illustrator instead of SVG or WebP.","If the file type reads as empty, re-save the file in an editor so the OS/browser assigns a proper MIME type."],"exampleFix":"// before\n<input type=\"file\" accept=\"*/*\" onChange={(e) => draft(e.target.files[0], \"icon\")} />\n// after\n<input type=\"file\" accept=\"image/png,image/jpeg\" onChange={(e) => draft(e.target.files[0], \"icon\")} />","handlingStrategy":"validation","validationCode":"function isPngOrJpeg(file: File): boolean {\n  return file.type === \"image/png\" || file.type === \"image/jpeg\";\n}\nif (!isPngOrJpeg(file)) { alert(\"Please choose a PNG or JPEG image.\"); return; }","typeGuard":"function isAcceptedImage(file: File): file is File & { type: \"image/png\" | \"image/jpeg\" } {\n  return file.type === \"image/png\" || file.type === \"image/jpeg\";\n}","tryCatchPattern":"try {\n  const asset = await createBrandAssetDraft(file, kind);\n} catch (error) {\n  showToast(error instanceof Error ? error.message : \"Could not use that image.\");\n}","preventionTips":["Set accept=\"image/png,image/jpeg\" on file inputs to filter at the OS picker level","Check file.type (not the extension) before processing any upload","Document accepted formats next to the upload control for end users","Convert SVG/WebP sources to PNG as part of the design handoff checklist"],"tags":["file-validation","image","mime-type"],"backgroundTag":"unsupported-file-type","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}