{"record":{"id":"0aa3fe8e822afa51","repo":"linshenkx/prompt-optimizer","slug":"not-a-png-file","errorCode":null,"errorMessage":"Not a PNG file","messagePattern":"Not a PNG file","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/ui/src/utils/favorite-share-export.ts","lineNumber":1286,"sourceCode":"\nconst crc32 = (bytes: Uint8Array): number => {\n  const table = getCrcTable()\n  let crc = 0xffffffff\n  for (const byte of bytes) {\n    crc = table[(crc ^ byte) & 0xff] ^ (crc >>> 8)\n  }\n  return (crc ^ 0xffffffff) >>> 0\n}\n\nconst isPng = (bytes: Uint8Array): boolean =>\n  PNG_SIGNATURE.every((byte, index) => bytes[index] === byte)\n\nexport const insertPngTextChunk = (\n  pngBytes: Uint8Array,\n  keyword: string,\n  text: string,\n): Uint8Array => {\n  if (!isPng(pngBytes)) throw new Error('Not a PNG file')\n  const encoder = new TextEncoder()\n  const type = encoder.encode('tEXt')\n  const data = encoder.encode(`${keyword}\\u0000${text}`)\n  const chunk = createPngChunk(type, data)\n\n  return insertPngChunkAfterIhdr(pngBytes, chunk)\n}\n\nexport const insertPngInternationalTextChunk = (\n  pngBytes: Uint8Array,\n  keyword: string,\n  text: string,\n  options: {\n    compressed?: boolean\n    languageTag?: string\n    translatedKeyword?: string\n  } = {},\n): Uint8Array => {","sourceCodeStart":1268,"sourceCodeEnd":1304,"githubUrl":"https://github.com/linshenkx/prompt-optimizer/blob/3e677b1d9f7e0493c142c175560531e7ae786dce/packages/ui/src/utils/favorite-share-export.ts#L1268-L1304","documentation":"Thrown by insertPngTextChunk when the input byte array fails the PNG signature check (isPng). The utility embeds a tEXt chunk into a PNG, so it requires a valid PNG file starting with the 8-byte PNG magic signature. Any non-PNG input (JPEG, WebP, corrupted bytes, or a data URL prefix that wasn't stripped) triggers this error.","triggerScenarios":"Calling insertPngTextChunk(pngBytes, keyword, text) with bytes that are not a PNG: a JPEG/WebP/GIF export, a truncated or modified byte array, or a canvas export that was requested as image/jpeg instead of image/png.","commonSituations":"Exporting images with toDataURL('image/jpeg') then passing decoded bytes to a PNG-embedding API; passing a screenshot re-encoded by the OS clipboard; passing base64 string directly instead of decoded Uint8Array; file picked with accept='image/*' instead of 'image/png'.","solutions":["Verify the input is a PNG before calling: check the first 8 bytes equal [137,80,78,71,13,10,26,10]","If the image may be another format, re-encode it via canvas: draw to a canvas and call toBlob(cb, 'image/png')","Ensure you decoded base64/data URL to Uint8Array before passing (strip the data:image/...;base64, prefix)","If the PNG came from an export pipeline, confirm no compression/transcoding step (e.g. optimizer) altered the file"],"exampleFix":"// before\nconst bytes = base64ToBytes(dataUrl) // dataUrl was 'data:image/jpeg;base64,...'\nconst out = insertPngTextChunk(bytes, 'key', 'value')\n\n// after\nconst pngDataUrl = await reEncodeAsPng(dataUrl)\nconst bytes = base64ToBytes(pngDataUrl.split(',')[1])\nif (!isPng(bytes)) throw new Error('Expected PNG')\nconst out = insertPngTextChunk(bytes, 'key', 'value')","handlingStrategy":"type-guard","validationCode":"const PNG_SIG = [137, 80, 78, 71, 13, 10, 26, 10]\nconst isPngBytes = (b: Uint8Array) =>\n  b.length >= 8 && PNG_SIG.every((v, i) => b[i] === v)\n\nif (!isPngBytes(bytes)) bytes = await reEncodeAsPng(bytes)","typeGuard":"const isPngBytes = (b: Uint8Array): b is Uint8Array & { __png: true } =>\n  b.length >= 8 && [137,80,78,71,13,10,26,10].every((v,i) => b[i] === v)","tryCatchPattern":"try {\n  const out = insertPngTextChunk(bytes, keyword, text)\n} catch (e) {\n  if (e instanceof Error && e.message === 'Not a PNG file') {\n    // convert source to PNG and retry, or notify user\n  } else throw e\n}","preventionTips":["Restrict file pickers to accept='image/png' or '.png'","Re-encode user images to PNG via canvas before embedding metadata","Always decode data URLs to raw bytes (strip prefix) before passing"],"tags":["png","image-processing","validation","file-format"],"backgroundTag":"invalid-file-format","analyzedSha":"3e677b1d9f7e0493c142c175560531e7ae786dce","analyzedAt":"2026-08-27T21:29:16.709Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}