{"record":{"id":"63c32a46f12dd448","repo":"stablyai/orca","slug":"failed-to-encode-resized-clipboard-image","errorCode":null,"errorMessage":"Failed to encode resized clipboard image","messagePattern":"Failed to encode resized clipboard image","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"mobile/src/session/use-mobile-terminal-paste.ts","lineNumber":39,"sourceCode":"  const base64 = source.replace(CLIPBOARD_IMAGE_DATA_URL_PREFIX_RE, '')\n  const file = new FsFile(Paths.cache, `orca-clip-resize-${Date.now()}.png`)\n  let context: ReturnType<typeof ImageManipulator.manipulate> | null = null\n  let rendered: Awaited<\n    ReturnType<ReturnType<typeof ImageManipulator.manipulate>['renderAsync']>\n  > | null = null\n  let resultUri: string | null = null\n  try {\n    file.create({ overwrite: true })\n    file.write(base64, { encoding: 'base64' })\n    context = ImageManipulator.manipulate(file.uri)\n    context.resize({ width: target.width, height: target.height })\n    rendered = await context.renderAsync()\n    const result = await rendered.saveAsync({ format: SaveFormat.PNG, base64: true })\n    resultUri = result.uri\n    // Why: empty base64 would pass the downstream base64 check and upload a corrupt\n    // image, so fail loudly here instead of silently sending an invalid payload.\n    if (!result.base64) {\n      throw new Error('Failed to encode resized clipboard image')\n    }\n    return { data: result.base64, width: result.width, height: result.height }\n  } finally {\n    rendered?.release()\n    context?.release()\n    if (resultUri) {\n      try {\n        new FsFile(resultUri).delete()\n      } catch {\n        // Best-effort cleanup; ImageManipulator saves into cache for every retry.\n      }\n    }\n    try {\n      file.delete()\n    } catch {\n      // Best-effort cleanup; the OS reclaims the cache directory regardless.\n    }\n  }","sourceCodeStart":21,"sourceCodeEnd":57,"githubUrl":"https://github.com/stablyai/orca/blob/1136503c6a231a16dce8f921f6fadb63d181e8db/mobile/src/session/use-mobile-terminal-paste.ts#L21-L57","documentation":"Thrown by the clipboard-image resize path when `expo-image-manipulator` rendered and saved the resized PNG but returned an empty/falsy base64. Sending an empty base64 would pass downstream checks and upload a corrupt image, so the loader fails loudly instead. Source came from Clipboard.getImageAsync.","triggerScenarios":"ImageManipulator produced a valid file (uri set) but no base64 string - seen on some iOS/Android versions when base64:true is passed but the encoded output is empty (memory pressure, very large source, or a platform bug).","commonSituations":"Pasting a very high-res screenshot/photo that survives decode but fails re-encode; low-memory device; expo-image-manipulator version regression; iOS HEIC source that decodes oddly.","solutions":["Retry the paste (often transient under memory pressure).","Use a smaller source image (downsample before paste).","Update expo-image-manipulator.","Fall back to text paste / save image and attach manually."],"exampleFix":"// before\nconst result = await rendered.saveAsync({ format: SaveFormat.PNG, base64: true })\nif (!result.base64) {\n  throw new Error('Failed to encode resized clipboard image')\n}\n// after - re-read the saved file as base64 when saveAsync omits it\nconst result = await rendered.saveAsync({ format: SaveFormat.PNG, base64: true })\nlet base64 = result.base64\nif (!base64 && result.uri) {\n  base64 = await FsFile.read(result.uri, { encoding: 'base64' })\n}\nif (!base64) {\n  throw new Error('Failed to encode resized clipboard image')\n}","handlingStrategy":"validation","validationCode":"const target = fitWithin(source, { width: 1024, height: 1024 }) // downsample before resize","typeGuard":"function hasBase64(r: { base64?: string } | null): r is { base64: string } {\n  return !!r && typeof r.base64 === 'string' && r.base64.length > 0\n}","tryCatchPattern":"try {\n  return await resizeMobileClipboardImage(source, target)\n} catch {\n  showToast('Could not process clipboard image', 1500)\n  return null\n}","preventionTips":["Cap source image dimensions before resize.","Retry resize once - empty base64 is often transient.","Keep expo-image-manipulator on a known-good version.","Provide a manual-attach fallback when resize fails."],"tags":["clipboard","image","expo-image-manipulator","paste","mobile"],"backgroundTag":null,"analyzedSha":"1136503c6a231a16dce8f921f6fadb63d181e8db","analyzedAt":"2026-08-12T23:15:58.167Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}