From abf42abd41bf444f0438e8bbfa4c53db7e9b149e Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Sun, 15 Feb 2026 00:19:16 +0100 Subject: [PATCH] fix: LINE webhook verification 200; fix tsgo error (#16582) (thanks @arosstale) --- CHANGELOG.md | 1 + src/line/monitor.ts | 4 ++-- src/line/webhook.ts | 2 +- src/memory/qmd-scope.ts | 5 ++++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 550cf7f93e7..76cde82eed7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Docs: https://docs.openclaw.ai ### Fixes - Telegram: when `channels.telegram.commands.native` is `false`, exclude plugin commands from `setMyCommands` menu registration while keeping plugin slash handlers callable. (#15132) Thanks @Glucksberg. +- LINE: return 200 OK for Developers Console "Verify" requests (`{"events":[]}`) without `X-Line-Signature`, while still requiring signatures for real deliveries. (#16582) Thanks @arosstale. - Cron: deliver text-only output directly when `delivery.to` is set so cron recipients get full output instead of summaries. (#16360) Thanks @thewilloftheshadow. - CLI/Plugins: ensure `openclaw message send` exits after successful delivery across plugin-backed channels so one-shot sends do not hang. (#16491) Thanks @yinghaosang. - CLI/Plugins: run registered plugin `gateway_stop` hooks before `openclaw message` exits (success and failure paths), so plugin-backed channels can clean up one-shot CLI resources. (#16580) Thanks @gumadeiras. diff --git a/src/line/monitor.ts b/src/line/monitor.ts index 6da220fbed3..0f436c14267 100644 --- a/src/line/monitor.ts +++ b/src/line/monitor.ts @@ -323,14 +323,14 @@ export async function monitorLineProvider( const signature = req.headers["x-line-signature"]; // LINE webhook verification sends POST {"events":[]} without a - // signature header. Return 200 so the LINE Developers Console + // signature header. Return 200 so the LINE Developers Console // "Verify" button succeeds. if (!signature || typeof signature !== "string") { try { const verifyBody = JSON.parse(rawBody) as WebhookRequestBody; if (Array.isArray(verifyBody.events) && verifyBody.events.length === 0) { logVerbose( - "line: webhook verification request (empty events, no signature) — 200 OK", + "line: webhook verification request (empty events, no signature) - 200 OK", ); res.statusCode = 200; res.setHeader("Content-Type", "application/json"); diff --git a/src/line/webhook.ts b/src/line/webhook.ts index 880786df517..9bccc290269 100644 --- a/src/line/webhook.ts +++ b/src/line/webhook.ts @@ -48,7 +48,7 @@ export function createLineWebhookMiddleware( if (rawBody) { const body = parseWebhookBody(req, rawBody); if (body && Array.isArray(body.events) && body.events.length === 0) { - logVerbose("line: webhook verification request (empty events, no signature) — 200 OK"); + logVerbose("line: webhook verification request (empty events, no signature) - 200 OK"); res.status(200).json({ status: "ok" }); return; } diff --git a/src/memory/qmd-scope.ts b/src/memory/qmd-scope.ts index da1bdcfc0e6..a31ad1fb54b 100644 --- a/src/memory/qmd-scope.ts +++ b/src/memory/qmd-scope.ts @@ -74,7 +74,10 @@ function parseQmdSessionScope(key?: string): ParsedQmdSessionScope { return { normalizedKey: normalized, chatType: "direct" }; } -function normalizeQmdSessionKey(key: string): string | undefined { +function normalizeQmdSessionKey(key?: string): string | undefined { + if (!key) { + return undefined; + } const trimmed = key.trim(); if (!trimmed) { return undefined;