Fix clipboard module crash on linux-arm-gnueabihf (#4596)

Fixes #4596

The @mariozechner/clipboard dependency was missing native bindings for
32-bit ARM Linux (linux-arm-gnueabihf), causing OpenClaw to crash on
startup on platforms like Raspberry Pi 3 and earlier.

This patch makes the clipboard module gracefully handle missing native
bindings by:
- Emitting a warning instead of throwing a fatal error
- Providing stub implementations that throw informative errors when called
- Allowing OpenClaw to start and run normally (clipboard ops will fail
  if called, but the pi-coding-agent should still work)

The patch is applied via pnpm's patch mechanism, which allows us to
modify the clipboard module at install time without forking it.
This commit is contained in:
spiceoogway 2026-01-30 11:03:16 -05:00
parent 938b0073bd
commit c2904c14ab
3 changed files with 104 additions and 2 deletions

View File

@ -250,6 +250,9 @@
"@sinclair/typebox": "0.34.47",
"hono": "4.11.4",
"tar": "7.5.4"
},
"patchedDependencies": {
"@mariozechner/clipboard@0.3.0": "patches/@mariozechner__clipboard@0.3.0.patch"
}
},
"vitest": {

View File

@ -0,0 +1,94 @@
diff --git a/index.js b/index.js
index 020b8893194bc185ec9ad4f5fd0558f148aee4d5..5ebf0beb60cc043c71092bd39d50f9f17d31e5bc 100644
--- a/index.js
+++ b/index.js
@@ -288,30 +288,66 @@ switch (platform) {
throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)
}
+// Provide stub implementations if native binding is not available
+// This allows the module to be required on unsupported platforms without crashing
if (!nativeBinding) {
- if (loadError) {
- throw loadError
+ const unsupportedPlatformError = new Error(
+ `Clipboard native bindings not available for ${platform}-${arch}. ` +
+ `Clipboard operations will not work. ` +
+ `Original error: ${loadError ? loadError.message : 'Unknown'}`
+ )
+
+ // Log warning but don't throw - allow the module to load
+ if (typeof process !== 'undefined' && process.emitWarning) {
+ process.emitWarning(unsupportedPlatformError.message, 'ClipboardUnsupportedPlatform')
+ } else {
+ console.warn('[clipboard]', unsupportedPlatformError.message)
+ }
+
+ // Provide stub implementations that throw informative errors when called
+ const notAvailable = (fnName) => {
+ return function() {
+ throw new Error(`Clipboard.${fnName} is not available on ${platform}-${arch}`)
+ }
}
- throw new Error(`Failed to load native binding`)
-}
-const { availableFormats, getText, setText, hasText, getImageBinary, getImageBase64, setImageBinary, setImageBase64, hasImage, getHtml, setHtml, hasHtml, getRtf, setRtf, hasRtf, clear, watch, callThreadsafeFunction } = nativeBinding
+ module.exports.availableFormats = notAvailable('availableFormats')
+ module.exports.getText = notAvailable('getText')
+ module.exports.setText = notAvailable('setText')
+ module.exports.hasText = notAvailable('hasText')
+ module.exports.getImageBinary = notAvailable('getImageBinary')
+ module.exports.getImageBase64 = notAvailable('getImageBase64')
+ module.exports.setImageBinary = notAvailable('setImageBinary')
+ module.exports.setImageBase64 = notAvailable('setImageBase64')
+ module.exports.hasImage = notAvailable('hasImage')
+ module.exports.getHtml = notAvailable('getHtml')
+ module.exports.setHtml = notAvailable('setHtml')
+ module.exports.hasHtml = notAvailable('hasHtml')
+ module.exports.getRtf = notAvailable('getRtf')
+ module.exports.setRtf = notAvailable('setRtf')
+ module.exports.hasRtf = notAvailable('hasRtf')
+ module.exports.clear = notAvailable('clear')
+ module.exports.watch = notAvailable('watch')
+ module.exports.callThreadsafeFunction = notAvailable('callThreadsafeFunction')
+} else {
+ const { availableFormats, getText, setText, hasText, getImageBinary, getImageBase64, setImageBinary, setImageBase64, hasImage, getHtml, setHtml, hasHtml, getRtf, setRtf, hasRtf, clear, watch, callThreadsafeFunction } = nativeBinding
-module.exports.availableFormats = availableFormats
-module.exports.getText = getText
-module.exports.setText = setText
-module.exports.hasText = hasText
-module.exports.getImageBinary = getImageBinary
-module.exports.getImageBase64 = getImageBase64
-module.exports.setImageBinary = setImageBinary
-module.exports.setImageBase64 = setImageBase64
-module.exports.hasImage = hasImage
-module.exports.getHtml = getHtml
-module.exports.setHtml = setHtml
-module.exports.hasHtml = hasHtml
-module.exports.getRtf = getRtf
-module.exports.setRtf = setRtf
-module.exports.hasRtf = hasRtf
-module.exports.clear = clear
-module.exports.watch = watch
-module.exports.callThreadsafeFunction = callThreadsafeFunction
+ module.exports.availableFormats = availableFormats
+ module.exports.getText = getText
+ module.exports.setText = setText
+ module.exports.hasText = hasText
+ module.exports.getImageBinary = getImageBinary
+ module.exports.getImageBase64 = getImageBase64
+ module.exports.setImageBinary = setImageBinary
+ module.exports.setImageBase64 = setImageBase64
+ module.exports.hasImage = hasImage
+ module.exports.getHtml = getHtml
+ module.exports.setHtml = setHtml
+ module.exports.hasHtml = hasHtml
+ module.exports.getRtf = getRtf
+ module.exports.setRtf = setRtf
+ module.exports.hasRtf = hasRtf
+ module.exports.clear = clear
+ module.exports.watch = watch
+ module.exports.callThreadsafeFunction = callThreadsafeFunction
+}

9
pnpm-lock.yaml generated
View File

@ -9,6 +9,11 @@ overrides:
hono: 4.11.4
tar: 7.5.4
patchedDependencies:
'@mariozechner/clipboard@0.3.0':
hash: uudcvs6o5uasebc7fqwj2zdl6m
path: patches/@mariozechner__clipboard@0.3.0.patch
importers:
.:
@ -6959,7 +6964,7 @@ snapshots:
'@mariozechner/clipboard-win32-x64-msvc@0.3.0':
optional: true
'@mariozechner/clipboard@0.3.0':
'@mariozechner/clipboard@0.3.0(patch_hash=uudcvs6o5uasebc7fqwj2zdl6m)':
optionalDependencies:
'@mariozechner/clipboard-darwin-arm64': 0.3.0
'@mariozechner/clipboard-darwin-universal': 0.3.0
@ -7030,7 +7035,7 @@ snapshots:
'@mariozechner/pi-coding-agent@0.49.3(ws@8.19.0)(zod@4.3.6)':
dependencies:
'@mariozechner/clipboard': 0.3.0
'@mariozechner/clipboard': 0.3.0(patch_hash=uudcvs6o5uasebc7fqwj2zdl6m)
'@mariozechner/jiti': 2.6.5
'@mariozechner/pi-agent-core': 0.49.3(ws@8.19.0)(zod@4.3.6)
'@mariozechner/pi-ai': 0.49.3(ws@8.19.0)(zod@4.3.6)