linshenkx/prompt-optimizer · error · Error
Desktop remote storage returned an unsupported binary payloa
Error message
Desktop remote storage returned an unsupported binary payload
What it means
Thrown by the desktop remote storage binary coercion helper when the payload returned from the desktop (Electron/Tauri IPC) remote storage layer is not one of the recognized binary types (ArrayBuffer, Uint8Array, other typed-array views, or byte array). It guards against structured-clone IPC returning unexpected shapes before backup processing continues.
Source
Thrown at packages/ui/src/utils/remote-backup.ts:656
if (body instanceof ArrayBuffer) return new Uint8Array(body.slice(0))
if (body instanceof Blob) return new Uint8Array(await body.arrayBuffer())
return new Uint8Array(0)
}
const copyUint8ArrayToArrayBuffer = (bytes: Uint8Array): ArrayBuffer => {
const view = new Uint8Array(bytes.byteLength)
view.set(bytes)
return view.buffer
}
const ipcBytesToArrayBuffer = (value: unknown): ArrayBuffer => {
if (value instanceof ArrayBuffer) return value.slice(0)
if (value instanceof Uint8Array) return copyUint8ArrayToArrayBuffer(value)
if (ArrayBuffer.isView(value)) {
return copyUint8ArrayToArrayBuffer(new Uint8Array(value.buffer, value.byteOffset, value.byteLength))
}
if (Array.isArray(value)) return copyUint8ArrayToArrayBuffer(new Uint8Array(value))
throw new Error('Desktop remote storage returned an unsupported binary payload')
}
const s3BodyToArrayBuffer = async (body: unknown): Promise<ArrayBuffer> => {
if (!body) return new ArrayBuffer(0)
if (body instanceof ArrayBuffer) return body
if (body instanceof Uint8Array) return copyUint8ArrayToArrayBuffer(body)
if (body instanceof Blob) return body.arrayBuffer()
const withArrayBuffer = body as { arrayBuffer?: () => Promise<ArrayBuffer> }
if (typeof withArrayBuffer.arrayBuffer === 'function') {
return withArrayBuffer.arrayBuffer()
}
const withByteArray = body as { transformToByteArray?: () => Promise<Uint8Array> }
if (typeof withByteArray.transformToByteArray === 'function') {
return copyUint8ArrayToArrayBuffer(await withByteArray.transformToByteArray())
}
View on GitHub (pinned to 3e677b1d9f)
Solutions
- Update the desktop app / IPC bridge so it returns ArrayBuffer or Uint8Array for binary payloads
- Convert the payload in the desktop handler before returning: buffer.buffer.slice(...) or new Uint8Array(buffer)
- Align desktop shell and UI package versions so the binary contract matches
- Log the actual value's constructor/type at the boundary to identify the mangling layer
Example fix
// desktop preload/handler: before
ipcMain.handle('read-backup', async (_e, id) => fs.readFile(path)) // returns Buffer-ish
// after
ipcMain.handle('read-backup', async (_e, id) => {
const buf = await fs.readFile(path)
return buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength) // ArrayBuffer
}) Defensive patterns
Strategy: type-guard
Validate before calling
const isSupportedBinary = (v: unknown): boolean => v instanceof ArrayBuffer || v instanceof Uint8Array || ArrayBuffer.isView(v) || Array.isArray(v)
Type guard
const isDesktopBinaryPayload = (v: unknown): v is ArrayBuffer | Uint8Array => v instanceof ArrayBuffer || v instanceof Uint8Array
Try / catch
try {
await readRemoteBinary(...)
} catch (error) {
if ((error as Error).message.includes('unsupported binary payload')) {
// desktop bridge contract broken: prompt user to update the desktop app
notifyDesktopUpdateRequired()
}
} Prevention
- Pin desktop shell and UI package to matching versions
- Always return ArrayBuffer from IPC handlers (never raw Node Buffer)
- Add a version handshake between UI and desktop bridge at startup
When it happens
Trigger: Desktop IPC bridge returning a Node Buffer-like object, Blob, plain object, string base64, or null-ish non-empty value that is not a view or array; serialization settings (e.g. ipcRenderer invoking with no ArrayBuffer transfer, or contextIsolation serialization) mangling binary data.
Common situations: Electron IPC serializing ArrayBuffers to something else when the handler forgets to copy/convert; desktop bridge version mismatch where the payload format changed (e.g. base64 string instead of bytes); Node Buffer passed directly (is a Uint8Array subclass but crossing a serialization boundary that strips it).
Related errors
- Failed to export favorites: ${errorMessage}
- Failed to serialize object for IPC: ${details}
- ${context}: ${response.status} ${message || response.statusT
- ${context}: ${(error as Error).message || String(error)}
- ${context}: ${(lastError as Error)?.message || String(lastEr
AI-assisted analysis of linshenkx/prompt-optimizer@3e677b1d9f (2026-08-27).
Data as JSON: /api/errors/1760e2d73101c731.
Report an issue: GitHub.