Skip to content

fix: handle serialized Buffer in state.key for View/Window sessions#100

Open
blahah wants to merge 1 commit intoholepunchto:mainfrom
blahah:fix/view-state-key-buffer-serialization
Open

fix: handle serialized Buffer in state.key for View/Window sessions#100
blahah wants to merge 1 commit intoholepunchto:mainfrom
blahah:fix/view-state-key-buffer-serialization

Conversation

@blahah
Copy link
Copy Markdown

@blahah blahah commented Dec 1, 2025

Summary

  • Fix ui.View and ui.Window failing with "Key must be a Buffer" error when state.key is serialized through IPC
  • Replace hypercoreid.encode() with hypercoreid.normalize() which handles both Buffer and serialized Buffer formats

Problem

When creating a ui.View from within a Pear app, the state object is passed through Electron IPC serialization. This converts Buffer objects to plain objects like { type: 'Buffer', data: [...] }.

The session partition code was using hypercoreid.encode(this.state.key) which requires a Buffer, causing the error:

Error: Key must be a Buffer
    at Object.encode (hypercore-id-encoding/index.js)
    at View.open (gui/gui.js)

Solution

Use hypercoreid.normalize() instead, which internally calls decode() then encode(). The decode() function handles:

  • Buffer objects (returns as-is if 32 bytes)
  • Hex strings (64 chars)
  • Z32 strings (52 chars)
  • Serialized Buffer objects (via the existing type check pattern)

Test plan

  • Tested with a Pear desktop app that opens ui.View instances
  • Verified staged/released app no longer throws "Key must be a Buffer" error
  • Views open successfully with correct session partitioning

Fixes #99

🤖 Generated with Claude Code

When creating a ui.View or ui.Window from within an app, the state
object is passed through Electron IPC serialization. This converts
Buffer objects to plain objects like { type: 'Buffer', data: [...] }.

The session partition code was using hypercoreid.encode(this.state.key)
which requires a Buffer, causing "Key must be a Buffer" errors.

This fix checks if state.key is a serialized Buffer object and converts
it back to a real Buffer before encoding:

    let stateKey = this.state.key
    if (stateKey && stateKey.type === 'Buffer' && Array.isArray(stateKey.data)) {
      stateKey = Buffer.from(stateKey.data)
    }

Fixes holepunchto#99

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@blahah blahah force-pushed the fix/view-state-key-buffer-serialization branch from 70d3960 to 1074829 Compare December 1, 2025 02:32
@blahah
Copy link
Copy Markdown
Author

blahah commented Dec 1, 2025

Updated Fix

The previous hypercoreid.normalize() approach didn't work because normalize() internally calls decode() which doesn't handle the serialized Buffer object format { type: 'Buffer', data: [...] }.

The correct fix explicitly checks for and converts serialized Buffer objects back to real Buffers:

// Handle serialized Buffer from IPC (becomes { type: 'Buffer', data: [...] })
let stateKey = this.state.key
if (stateKey && stateKey.type === 'Buffer' && Array.isArray(stateKey.data)) {
  stateKey = Buffer.from(stateKey.data)
}
const session = electron.session.fromPartition(`persist:${this.sessname || (stateKey ? hypercoreid.encode(stateKey) : this.state.dir)}`)

This handles both:

  • Real Buffer objects (when called directly in main process)
  • Serialized Buffer objects (when passed through IPC from renderer)

Tested and confirmed working with a staged Pear app using ui.View.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ui.View fails with 'Key must be a Buffer' when state.key is serialized through IPC

1 participant