diff --git a/scripts/entrypoint.sh b/scripts/entrypoint.sh index 864eb0c..b1d3192 100644 --- a/scripts/entrypoint.sh +++ b/scripts/entrypoint.sh @@ -302,6 +302,62 @@ nginx rm -f /tmp/openclaw-gateway.lock 2>/dev/null || true rm -f "$STATE_DIR/gateway.lock" 2>/dev/null || true +# ── LINE webhook route hot-reload workaround ───────────────────────────────── +# Bug: openclaw/openclaw#49803 — LINE (and other webhook-based channels) return +# 404 on cold start because the bundler splits runtime.ts into two chunks. The +# chunk that registers LINE routes and the chunk the HTTP server uses to look up +# routes both initialise the same global "route registry" object — but whichever +# chunk runs first creates the object without the fields the other chunk expects, +# so they end up referencing different registries. Result: routes are registered +# successfully (no error logged) but the HTTP server can't find them → 404. +# +# After a config hot-reload the channel restarts and re-registers routes into the +# correct registry, so the 404 goes away. The workaround below triggers that +# hot-reload automatically 20 seconds after the gateway starts. +# +# How it works: +# 1. Waits 20 s for the gateway to fully start and load all channel plugins. +# 2. Writes a temporary "_reloadTs" field into openclaw.json — the gateway's +# file-watcher sees the change and hot-reloads the LINE channel. +# 3. Removes the temporary field 5 s later (clean-up). +# +# This is a background process — it does NOT block gateway startup. +# Remove this block once openclaw/openclaw#49803 is fixed upstream and the +# upstream fix is merged and shipped in a release we build from. +# +# Upstream PRs tracking the real fix: +# - openclaw/openclaw#53642 (bundle-split registry mismatch fix) +# - openclaw/openclaw#54686 (syncPluginRegistry at runtime boundaries) +CONFIG_FILE="${STATE_DIR}/openclaw.json" +( + sleep 20 + if [ -f "$CONFIG_FILE" ]; then + echo "[entrypoint] applying LINE webhook route hot-reload workaround (#49803)..." + # Add a temporary field to trigger the file-watcher hot-reload + node -e " + const fs = require('fs'); + try { + const c = JSON.parse(fs.readFileSync(process.argv[1], 'utf8')); + c._reloadTs = Date.now(); + fs.writeFileSync(process.argv[1], JSON.stringify(c, null, 2)); + } catch(e) { process.exit(0); } + " "$CONFIG_FILE" + sleep 5 + # Remove the temporary field + node -e " + const fs = require('fs'); + try { + const c = JSON.parse(fs.readFileSync(process.argv[1], 'utf8')); + delete c._reloadTs; + fs.writeFileSync(process.argv[1], JSON.stringify(c, null, 2)); + } catch(e) { process.exit(0); } + " "$CONFIG_FILE" + echo "[entrypoint] LINE webhook route hot-reload complete." + else + echo "[entrypoint] WARNING: config not found at $CONFIG_FILE — skipping LINE hot-reload workaround" + fi +) & + # ── Start openclaw gateway ─────────────────────────────────────────────────── echo "[entrypoint] starting openclaw gateway on port $GATEWAY_PORT..."