{"record":{"id":"904b9a9bbb9f9ccc","repo":"different-ai/openwork","slug":"use-a-square-icon-at-least-64-64-pixels","errorCode":null,"errorMessage":"Use a square icon at least 64×64 pixels.","messagePattern":"Use a square icon at least 64×64 pixels\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"ee/apps/den-web/app/(den)/dashboard/_components/brand-appearance-screen.tsx","lineNumber":46,"sourceCode":"  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.\");\n    if (aspectRatio < 1.5 || aspectRatio > 8) throw new Error(\"Use a horizontal wordmark between 1.5:1 and 8:1.\");\n  }\n\n  return { file, previewUrl: URL.createObjectURL(file), width, height };\n}\n\nfunction BrandAssetUploadField({\n  kind,\n  title,\n  description,\n  currentUrl,\n  managedAsset,\n  draft,\n  clearPending,","sourceCodeStart":28,"sourceCodeEnd":64,"githubUrl":"https://github.com/different-ai/openwork/blob/2b7df46e8ae1517d64c896c7793d2d52ec845669/ee/apps/den-web/app/(den)/dashboard/_components/brand-appearance-screen.tsx#L28-L64","documentation":"For kind === \"icon\", the decoded image must be at least 64×64 pixels on both axes; smaller icons are rejected because the icon is rendered at sizes up to 64px in the dashboard and marketplace and would look blurry.","triggerScenarios":"Uploading an app icon where width < 64 or height < 64 — e.g. a 32×32 favicon or 48×48 toolbar icon chosen as the app icon.","commonSituations":"Grabbing the favicon.ico from a website; exporting the icon from a small design frame; reusing a legacy low-res app icon.","solutions":["Re-export the icon at 512×512 (or at least 64×64) PNG.","Draw/upscale the source art at native resolution rather than scaling up a 32px bitmap.","Use a 1024×1024 master icon asset and downscale per-use in design tools.","Verify dimensions before upload: if (img.width >= 64 && img.height >= 64) proceed."],"exampleFix":"// before\nawait draft(tinyFavicon /* 32x32 */, \"icon\");\n// after\nawait draft(highResIconPng /* 512x512 */, \"icon\");","handlingStrategy":"validation","validationCode":"async function isIconBigEnough(file: File): Promise<boolean> {\n  const bmp = await createImageBitmap(file);\n  const ok = bmp.width >= 64 && bmp.height >= 64;\n  bmp.close();\n  return ok;\n}","typeGuard":null,"tryCatchPattern":"try {\n  const asset = await createBrandAssetDraft(file, \"icon\");\n} catch (error) {\n  showToast(error instanceof Error ? error.message : \"Could not use that image.\");\n}","preventionTips":["Use a 512×512 master icon and downscale per use case","Do not reuse favicons (16–48px) as app icons","Preview icon dimensions in the upload UI before submission","Keep a design-system icon export preset that always emits ≥64×64 PNG"],"tags":["image-validation","dimensions","icon"],"backgroundTag":"invalid-image-dimensions","analyzedSha":"2b7df46e8ae1517d64c896c7793d2d52ec845669","analyzedAt":"2026-09-01T07:59:23.713Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}