openclaw - ✅(Solved) Fix [Bug]: message(action=send) injects empty poll fields, causing normal text sends to fail [3 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#48928Fetched 2026-04-08 00:50:56
View on GitHub
Comments
1
Participants
2
Timeline
9
Reactions
0
Author
Participants
Timeline (top)
cross-referenced ×3labeled ×2referenced ×2commented ×1

Normal text sends via message(action=send) fail when empty/default poll fields are present, due to incorrect poll intent detection.

Error Message

Failing evidence

Exact error: Poll fields require action \"poll\"; use action \"poll\" instead of \"send\". Observed default poll fields present in a normal send request:

  • pollQuestion: \"\"
  • pollOption: []
  • pollDurationHours: 0

Root cause evidence

In the runtime bundles, hasPollCreationParams() treated any finite numeric value as poll intent, including 0:

if (typeof value === "number" && Number.isFinite(value)) return true;

This caused pollDurationHours: 0 to be interpreted as poll creation intent.

Validation after local hotfix

After changing the numeric poll-intent check so 0 no longer counts as poll intent, the same Feishu text send succeeded with:

  • ok: true
  • messageId: om_x100b54a6481d14b4c3e8176d1f2e50f
  • chatId: oc_3523028906e17dbcf5687b430cf32985

Root Cause

Root cause evidence

In the runtime bundles, hasPollCreationParams() treated any finite numeric value as poll intent, including 0:

Fix Action

Fix / Workaround

Validation after local hotfix

After changing the numeric poll-intent check so 0 no longer counts as poll intent, the same Feishu text send succeeded with:

  • ok: true
  • messageId: om_x100b54a6481d14b4c3e8176d1f2e50f
  • chatId: oc_3523028906e17dbcf5687b430cf32985

PR fix notes

PR #49110: fix poll send false-positive when duration sentinel is zero

Description (problem / solution / changelog)

AI-assisted: Codex

Fixes #48928.

Summary

This change prevents message(action=send) calls from being misclassified as poll creation requests when poll duration fields are present only as zero-value sentinels.

Root Cause

hasPollCreationParams treated any finite numeric poll field as poll intent, including 0 and stringified "0". That caused send actions carrying zero-valued placeholders to trip the Poll fields require action "poll" guard even though no poll was being created.

Fix

The numeric poll-intent check now only treats positive finite values as poll creation parameters. The regression coverage also verifies that send remains allowed when pollDurationHours=0 is present, while valid positive poll durations still behave as poll creation intent.

Validation

  • pnpm exec vitest run "src/poll-params.test.ts" "src/infra/outbound/message-action-runner.context.test.ts" "src/infra/outbound/message-action-runner.poll.test.ts"

Changed files

  • src/infra/outbound/message-action-runner.context.test.ts (modified, +11/-0)
  • src/poll-params.test.ts (modified, +4/-2)
  • src/poll-params.ts (modified, +6/-2)

PR #49516: fix: ignore empty/default poll params for message(action=send)

Description (problem / solution / changelog)

Summary

Describe the problem and fix in 2–5 bullets:

  • Problem: message(action=send) could reject normal text sends when empty/default poll fields were present, especially pollDurationHours: 0.
  • Why it matters: this breaks normal outbound messaging before the request reaches the target integration/channel.
  • What changed: tightened poll-intent detection so numeric poll params only count when they are finite and greater than 0, and added regression coverage.
  • What did NOT change (scope boundary): this PR does not change real poll creation behavior, channel-specific poll handling, or unrelated message validation paths.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #48928
  • Related #None

User-visible / Behavior Changes

Normal message(action=send) requests no longer get misclassified as poll creation just because empty/default poll fields are present (for example pollQuestion: "", pollOption: [], pollDurationHours: 0).

Security Impact (required)

  • New permissions/capabilities? (No)
  • Secrets/tokens handling changed? (No)
  • New/changed network calls? (No)
  • Command/tool execution surface changed? (No)
  • Data access scope changed? (No)
  • If any Yes, explain risk + mitigation:

None.

Repro + Verification

Environment

  • OS: macOS (local development machine)
  • Runtime/container: Node.js local checkout
  • Model/provider: N/A
  • Integration/channel (if any): Feishu on the original failing path
  • Relevant config (redacted): standard local OpenClaw checkout; no config change required for the source fix

Steps

  1. Call message(action=send) for a normal text send.
  2. Include empty/default poll-related fields such as:
  • pollQuestion: ""
  • pollOption: []
  • pollDurationHours: 0
  1. Observe validation before provider delivery.

Expected

  • The request should stay on the normal send path.
  • Empty/default poll fields should not be treated as poll creation intent.

Actual

  • The request was rejected with:
  • Poll fields require action "poll"; use action "poll" instead of "send".

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

What you personally verified (not just CI), and how:

  • Verified scenarios:
  • Reviewed the failing logic in hasPollCreationParams()
  • Confirmed the source fix changes numeric poll-intent detection from any finite number to finite numbers greater than 0
  • Ran pnpm check locally successfully
  • Added regression coverage for pollDurationHours: 0, "0", and a send-path case with empty/default poll fields
  • Edge cases checked:
  • Positive numeric values like 60 and "60" still count as poll intent
  • Empty/default values like 0 and "0" do not
  • What you did not verify:
  • I did not get a clean local pass on the targeted Vitest command because the local environment hit a Node/Vitest runtime issue: Unexpected status of a module that is imported again after being required. Status = 0

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? (Yes)
  • Config/env changes? (No)
  • Migration needed? (No)
  • If yes, exact upgrade steps:

None.

Failure Recovery (if this breaks)

Changed files

  • src/infra/outbound/message-action-runner.context.test.ts (modified, +17/-0)
  • src/poll-params.test.ts (modified, +3/-2)
  • src/poll-params.ts (modified, +3/-2)

PR #52141: fix(message): ignore zero-valued poll defaults in send path

Description (problem / solution / changelog)

Fixes #52118.

Summary

  • treat zero-valued numeric poll params as unset in hasPollCreationParams()
  • keep non-zero numeric poll params as poll intent
  • add regression coverage for message.send with zero-valued poll defaults present

Why

message.send currently rejects normal send/file operations when callers include poll numeric defaults like:

  • pollDurationHours: 0
  • pollDurationSeconds: 0

Those zero values are currently interpreted as poll creation intent, which is too broad for send-path validation.

Changes

  • src/poll-params.ts
    • numeric poll params now count as poll intent only when non-zero
  • src/poll-params.test.ts
    • update helper expectations for 0 / "0"
  • src/infra/outbound/message-action-runner.plugin-dispatch.test.ts
    • add regression test proving send still uses the send path when zero-valued poll defaults are present

Validation

Ran targeted tests:

  • src/poll-params.test.ts
  • src/infra/outbound/message-action-runner.plugin-dispatch.test.ts

Both passed locally.

Related

Related: #48928 #51830 #48870 #48730 #42820 #43015

Changed files

  • src/infra/outbound/message-action-runner.plugin-dispatch.test.ts (modified, +60/-0)
  • src/poll-params.test.ts (modified, +5/-2)
  • src/poll-params.ts (modified, +6/-3)

Code Example

### Failing evidence
Exact error:
`Poll fields require action \"poll\"; use action \"poll\" instead of \"send\".`
Observed default poll fields present in a normal send request:
- `pollQuestion: \"\"`
- `pollOption: []`
- `pollDurationHours: 0`

### Root cause evidence
In the runtime bundles, `hasPollCreationParams()` treated any finite numeric value as poll intent, including `0`:

if (typeof value === \"number\" && Number.isFinite(value)) return true;

This caused `pollDurationHours: 0` to be interpreted as poll creation intent.

### Validation after local hotfix
After changing the numeric poll-intent check so `0` no longer counts as poll intent, the same Feishu text send succeeded with:
- `ok: true`
- `messageId: om_x100b54a6481d14b4c3e8176d1f2e50f`
- `chatId: oc_3523028906e17dbcf5687b430cf32985`
RAW_BUFFERClick to expand / collapse

Bug type

Behavior bug (incorrect output/state without crash)

Summary

Normal text sends via message(action=send) fail when empty/default poll fields are present, due to incorrect poll intent detection.

Steps to reproduce

  1. Use the message tool to send a normal text message.
  2. Example intent:
    • action: \"send\"
    • channel: \"feishu\"
    • target: \"user:ou_xxx\"
    • message: \"hello\"
    1. Observe that the executed request includes empty/default poll fields such as:
    • pollQuestion: \"\"
    • pollOption: []
    • pollDurationHours: 0
    1. The send is rejected before reaching the provider with:
    • Poll fields require action \"poll\"; use action \"poll\" instead of \"send\".

Expected behavior

A normal text send with action=\"send\" should succeed. Empty/default poll fields should not cause OpenClaw to treat the request as poll creation.

Actual behavior

OpenClaw rejects a normal message(action=send) request as if it were poll creation, with: Poll fields require action \"poll\"; use action \"poll\" instead of \"send\". In our case, the failure happened before the message reached Feishu.

OpenClaw version

2026.3.7

Operating system

Linux 6.6.117-45.1.oc9.x86_64 (x64)

Install method

Global pnpm install. Observed install path: /root/.local/share/pnpm/global/5/.pnpm/[email protected]_.../node_modules/openclaw CLI wrapper path: /usr/local/bin/openclaw

Model

gpt-5.4

Provider / routing chain

Model provider used in this environment: lan Observed routing chain for the failing path: assistant/tool call -> OpenClaw message(action=send) validation -> rejected inside OpenClaw before provider delivery For the reproduced failing case, the target provider/channel was Feishu.

Config file / key location

Primary config file: ~/.openclaw/openclaw.json Gateway status in this environment reported: - CLI config: ~/.openclaw/openclaw.json - Service config: ~/.openclaw/openclaw.json

Additional provider/model setup details

  • Primary messaging channel in this environment is Feishu.
  • The issue is not specific to model reasoning output or prompt formatting.
  • The failure is in the OpenClaw message execution path, specifically poll-intent detection during message(action=send) validation.

Logs, screenshots, and evidence

### Failing evidence
Exact error:
`Poll fields require action \"poll\"; use action \"poll\" instead of \"send\".`
Observed default poll fields present in a normal send request:
- `pollQuestion: \"\"`
- `pollOption: []`
- `pollDurationHours: 0`

### Root cause evidence
In the runtime bundles, `hasPollCreationParams()` treated any finite numeric value as poll intent, including `0`:

if (typeof value === \"number\" && Number.isFinite(value)) return true;

This caused `pollDurationHours: 0` to be interpreted as poll creation intent.

### Validation after local hotfix
After changing the numeric poll-intent check so `0` no longer counts as poll intent, the same Feishu text send succeeded with:
- `ok: true`
- `messageId: om_x100b54a6481d14b4c3e8176d1f2e50f`
- `chatId: oc_3523028906e17dbcf5687b430cf32985`

Impact and severity

Severity: High This breaks normal text message delivery for any path that ultimately relies on message(action=send) while empty/default poll fields are present. Impact includes:

  • Direct bot sends fail
  • Agent-mediated send attempts fail if they end up on the same message(action=send) path
  • The failure is deterministic and blocks normal outbound messaging

Additional information

This is an OpenClaw bug. The request is rejected inside OpenClaw before it reaches Feishu. The effective fix is to change poll-intent detection so empty/default numeric values like pollDurationHours: 0 do not count as poll creation intent. A more robust fix would also strip empty/default poll fields before validation for action=\"send\". If you want, I can also give you a tighter GitHub form version with each field shortened to 1 to 3 lines."

extent analysis

Fix Plan

To resolve the issue, we need to modify the poll-intent detection logic in OpenClaw. The fix involves two steps:

  • Modify the hasPollCreationParams() function to ignore 0 as a poll intent indicator.
  • Strip empty/default poll fields before validation for action="send".

Here's an example of how the modified hasPollCreationParams() function could look:

function hasPollCreationParams(value) {
  if (typeof value === "number" && Number.isFinite(value) && value > 0) return true;
  // Additional checks for other poll creation params...
}

Additionally, we can strip empty/default poll fields before validation:

function stripDefaultPollFields(message) {
  if (message.pollQuestion === "") delete message.pollQuestion;
  if (message.pollOption.length === 0) delete message.pollOption;
  if (message.pollDurationHours === 0) delete message.pollDurationHours;
  return message;
}

// Usage:
const message = { /* original message object */ };
const strippedMessage = stripDefaultPollFields(message);
// Proceed with validation using strippedMessage

Verification

To verify that the fix worked, you can test sending a normal text message with empty/default poll fields using the message tool. The message should be delivered successfully without being rejected due to poll intent detection.

Extra Tips

  • Make sure to update the OpenClaw version to include the modified hasPollCreationParams() function and the stripDefaultPollFields() function.
  • Consider adding additional checks to handle other edge cases that may arise from poll intent detection.
  • If you're using a custom implementation of OpenClaw, ensure that you apply the fixes to your custom codebase as well.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

FAQ

Expected behavior

A normal text send with action=\"send\" should succeed. Empty/default poll fields should not cause OpenClaw to treat the request as poll creation.

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix [Bug]: message(action=send) injects empty poll fields, causing normal text sends to fail [3 pull requests, 1 comments, 2 participants]