openclaw - ✅(Solved) Fix Discord: asVoice conflicts with required components schema — cannot send voice messages with pre-recorded audio [1 pull requests, 2 comments, 3 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#51447Fetched 2026-04-08 01:11:08
View on GitHub
Comments
2
Participants
3
Timeline
5
Reactions
0
Author
Timeline (top)
commented ×2referenced ×2cross-referenced ×1

Error Message

  • asVoice: true + media: /path/to/audio.ogg (no components) → Validation error: components: must have required property components
  • asVoice: true + media + components: {} → API error: Discord components cannot be sent as voice messages.

Fix Action

Workaround

The tts tool can send inline playable audio, but it uses the bot's own TTS voice — not custom/cloned audio. There is no way to send pre-recorded custom audio as a playable voice message through the current tool.

PR fix notes

PR #51544: fix: make Discord components optional in tool schema for voice messages

Description (problem / solution / changelog)

Summary

  • Problem: Discord components property is contributed as required in the message tool JSON schema, so any message tool call that omits components fails validation — including voice messages with asVoice: true
  • Why it matters: Agents cannot send Discord voice messages at all — schema rejects before runtime. With components it errors "cannot send components as voice messages." Without components it errors "must have required property 'components'." No valid path exists.
  • What changed: Wrapped the components schema contribution in Type.Optional() in extensions/discord/src/channel-actions.ts
  • What did NOT change (scope boundary): No runtime logic, no voice message infrastructure, no component rendering. One line in schema definition.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • 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 #51447

User-visible / Behavior Changes

  • Agents can now omit components when calling the message tool on Discord channels (voice messages, plain text, media attachments)
  • Previously required components field is now optional, matching the runtime's actual expectations

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

Repro + Verification

Environment

  • OS: macOS 26.4 (arm64)
  • Runtime/container: Node 25.6.1
  • Model/provider: Any (schema-level issue, model-agnostic)
  • Integration/channel: Discord
  • Relevant config: Discord channel with bot token configured

Steps

  1. Configure a Discord channel in OpenClaw
  2. Have an agent call message with action: "send", asVoice: true, and an audio file — without components
  3. Observe validation error: "must have required property 'components'"
  4. Add components: {} — observe runtime error: "components cannot be sent as voice messages"

Expected

  • Voice message sends successfully without components field

Actual

  • Schema validation blocks the call before runtime

Evidence

  • Failing test/log before + passing after
  • Trace/log snippets

All existing tests pass after the change:

  • extensions/discord/src/actions/runtime.test.ts — 40/40 ✅
  • extensions/discord/src/voice-message.test.ts — 4/4 ✅
  • src/channels/plugins/message-actions.test.ts — 5/5 ✅
  • Full pnpm check passes

Human Verification (required)

  • Verified scenarios: Ran all Discord extension tests, voice message tests, and message action contract tests locally. All pass.
  • Edge cases checked: Confirmed components can still be passed when provided (existing functionality preserved). Confirmed asVoice: true without components no longer fails schema validation.
  • What I did not verify: End-to-end voice message send to a live Discord channel (blocked by the voice message infrastructure needing a running gateway with bot connected). The runtime voice message code path (ensureOggOpus, generateWaveform, sendDiscordVoiceMessage) was not changed.

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 — previously required field becomes optional; all existing calls that include components still work
  • Config/env changes? No
  • Migration needed? No

Failure Recovery (if this breaks)

  • How to disable/revert this change quickly: Revert the single commit; remove Type.Optional() wrapper
  • Files/config to restore: extensions/discord/src/channel-actions.ts
  • Known bad symptoms reviewers should watch for: If components somehow needs to be required for a different code path (none found), agents would get unexpected undefined for components

Risks and Mitigations

  • Risk: Agent sends malformed components that previously would have been caught by required-field validation
    • Mitigation: The components object still has its full internal schema validation — only the top-level presence check changed from required to optional

AI Disclosure

  • AI-assisted (built with OpenClaw Builder agent using Claude Opus 4.6)
  • Fully tested locally (pnpm check, targeted test suites)
  • I understand what the code does — one-line schema change wrapping components in Type.Optional()

Changed files

  • extensions/discord/src/channel-actions.ts (modified, +2/-1)
RAW_BUFFERClick to expand / collapse

Bug

The message tool requires components for Discord sends, but Discord voice messages (asVoice: true) cannot have components. This makes it impossible to send pre-recorded audio as inline playable voice messages in Discord.

Steps to Reproduce

  1. Try sending a voice message with pre-recorded audio:

    • asVoice: true + media: /path/to/audio.ogg (no components) → Validation error: components: must have required property components
    • asVoice: true + media + components: {} → API error: Discord components cannot be sent as voice messages.
  2. Try sending audio without asVoice:

    • media + components: { blocks: [{ type: "file", file: "attachment://file.ogg" }] } → File attaches as download card, NOT inline playable
    • media + components: { text: "..." } → Attachment silently stripped (attachments: [])

Expected Behavior

Sending asVoice: true with media and no components should work. Discord voice messages need duration_secs and waveform metadata on the attachment — the tool should either:

  1. Skip components validation when asVoice: true
  2. Auto-generate waveform data from the audio file (like Discord clients do)

Actual Behavior

Caught between two constraints: components is required but voice messages cannot have components.

Workaround

The tts tool can send inline playable audio, but it uses the bot's own TTS voice — not custom/cloned audio. There is no way to send pre-recorded custom audio as a playable voice message through the current tool.

Environment

  • OpenClaw 2026.3.14
  • Discord channel
  • macOS arm64

extent analysis

Fix Plan

To fix this issue, we need to modify the message tool to either skip components validation when asVoice: true or auto-generate waveform data from the audio file. Here are the steps:

  • Modify the validation logic to check for asVoice: true and skip components validation if it's true.
  • Add a new function to auto-generate waveform data from the audio file using a library like ffmpeg.
  • Update the message tool to use the new function to generate waveform data when asVoice: true.

Example Code

// Modified validation logic
if (asVoice && !components) {
  // Skip components validation
} else {
  // Existing validation logic
}

// New function to auto-generate waveform data
const generateWaveform = (audioFile) => {
  // Use ffmpeg to generate waveform data
  const ffmpeg = require('fluent-ffmpeg');
  const waveform = ffmpeg(audioFile)
    .outputOptions('-f', 'wav')
    .outputOptions('-ar', '44.1k')
    .outputOptions('-ac', '2')
    .outputOptions('-acodec', 'pcm_s16le')
    .output('pipe:')
    .on('end', () => {
      // Generate waveform data from the audio file
      const waveformData = [];
      // ...
      return waveformData;
    });
  return waveform;
};

// Update the message tool to use the new function
if (asVoice) {
  const waveformData = generateWaveform(media);
  // Add waveform data to the attachment metadata
  attachment.metadata = {
    duration_secs: audioDuration,
    waveform: waveformData,
  };
}

Verification

To verify that the fix worked, try sending a voice message with pre-recorded audio using the modified message tool. The audio should be sent as an inline playable voice message with the correct waveform data.

Extra Tips

  • Make sure to test the fix with different audio file formats and durations to ensure that the waveform data is generated correctly.
  • Consider adding error handling to the generateWaveform function to handle cases where the audio file is invalid or cannot be processed.

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…

Still need to ship something?

×6

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

Back to top recommendations

TRENDING