April 27, 2026 โ€ข Version: Latest (unversioned)

Discord Slash Command Returns 'Done.' Instead of Rich Data

Regression in OpenClaw v Latest where the /status slash command displays 'Done.' text instead of displaying the expected rich embedded data response.

๐Ÿ” Symptoms

The /status Discord slash command executes without throwing visible errors but returns only a plain text “Done.” message instead of the expected rich embedded data.

CLI Execution Examples

When the command is invoked, the bot responds with minimal output:

User: /status
Bot: Done.

Expected Response (prior behavior):

User: /status
Bot: [Rich embedded message with status information, model info, system metrics, etc.]

Diagnostic Indicators

  • Exit code: 0 (command completes successfully)
  • No error logs in console output
  • Response arrives promptly (not timing out)
  • Command works in text channel context but fails in DM context
  • Bot has proper APPLICATION_COMMANDS permission scope

Secondary Symptoms

  • Interaction acknowledgment may appear as “Thinking…" before reverting to “Done.”
  • Response lacks embedded formatting, colors, or fields
  • Timestamp on message shows correct execution time
  • Subsequent commands continue to work normally

๐Ÿง  Root Cause

The “Done.” response is the default Discord.js fallback message when an interaction response is not properly created or edited after initial acknowledgment.

Technical Failure Sequence

  1. Interaction Received: Discord sends the INTERACTION_CREATE event to the OpenClaw handler
  2. Initial Acknowledgment: OpenClaw calls interaction.reply() with { content: "Done." } as a default fallback
  3. Handler Execution: The actual status handler begins processing data
  4. Response Failure: The handler attempts to use interaction.editReply() or interaction.followUp()
  5. Missing Callback Resolution: The response never reaches the follow-up method due to:
    • Async/await not properly awaited in the handler chain
    • Promise rejection silently swallowed
    • Interaction object reference becoming stale
  6. Default Display: Discord renders the initial "Done." acknowledgment

Architectural Inconsistency

OpenClaw’s Discord adapter changed how interaction deferred responses are handled:

Before (working):

await interaction.reply({ embeds: [statusEmbed] });

After (broken):

await interaction.deferReply();  // Implicit acknowledgment with "Done."
// ... async processing ...
await interaction.editReply({ embeds: [statusEmbed] });  // Fails silently

The deferral pattern assumes the follow-up edit will complete successfully. Any exception in the processing chain causes the “Done.” to persist.

Specific Code Paths Affected

  • src/adapters/discord/interaction-handler.ts: Missing try-catch around response editing
  • src/commands/status/index.ts: Handler may not properly await data fetching
  • src/providers/openclaw/status-service.ts: Data retrieval may throw in certain environments

๐Ÿ› ๏ธ Step-by-Step Fix

Modify the status command handler to respond directly without deferral:

// Before (causes regression)
statusCommand: async (interaction) => {
    await interaction.deferReply();
    const status = await fetchStatusData();
    await interaction.editReply({ embeds: [buildEmbed(status)] });
}

// After (correct)
statusCommand: async (interaction) => {
    const status = await fetchStatusData();
    await interaction.reply({ embeds: [buildEmbed(status)] });
}

Method 2: Add Robust Error Handling

Wrap the deferred response flow with comprehensive error handling:

statusCommand: async (interaction) => {
    await interaction.deferReply({ ephemeral: false }).catch(err => {
        console.error('Defer failed:', err);
        throw err;  // Propagate to prevent silent failure
    });

    try {
        const status = await fetchStatusData();
        const embed = buildEmbed(status);
        await interaction.editReply({ embeds: [embed] }).catch(err => {
            console.error('EditReply failed:', err);
            await interaction.reply({ embeds: [embed] });  // Fallback
        });
    } catch (error) {
        console.error('Status fetch failed:', error);
        await interaction.editReply({
            content: 'โš ๏ธ Failed to retrieve status information.',
            embeds: []
        }).catch(() => {
            await interaction.reply('โš ๏ธ Failed to retrieve status information.');
        });
    }
}

Method 3: Verify Adapter Configuration

Ensure the Discord adapter is configured correctly in your OpenClaw setup:

// openclaw.config.ts
export default {
    adapters: {
        discord: {
            intents: ['Guilds', 'GuildMessages', 'DirectMessages'],
            // Explicitly set response mode
            useLegacyContextMenus: false,
            respondOnDefer: false  // Disable implicit "Done." responses
        }
    }
}

Method 4: Check Slash Command Registration

Force re-registration of the slash command to ensure proper permissions:

# Remove existing command
npx openclaw discord commands delete status --guild YOUR_GUILD_ID

# Clear global cache
npx openclaw discord cache clear

# Re-register
npx openclaw discord commands register

# Verify registration
npx openclaw discord commands list

๐Ÿงช Verification

Test Commands

1. Verify Command Registration:

npx openclaw discord commands list --verbose
# Expected: /status command appears with correct description and options

2. Test in Public Channel:

# In a text channel (not DM)
/status
# Expected: Rich embed with status data visible to all users

3. Test in DM Context:

# In bot DM
/status
# Expected: Rich embed with status data
# If still shows "Done.": Issue is in DM-specific handling

4. Enable Debug Logging:

# Set environment variable
export LOG_LEVEL=debug
export DEBUG=openclaw:discord:*

# Restart OpenClaw
npx openclaw start

# Execute /status and observe logs
# Look for: "interaction.reply", "interaction.deferReply", "interaction.editReply"

Expected Log Output (Fixed State)

[DEBUG] openclaw:discord:interaction - Received INTERACTION_CREATE for /status
[DEBUG] openclaw:discord:interaction - Calling status handler
[DEBUG] openclaw:discord:interaction - Fetching status data from provider
[DEBUG] openclaw:discord:interaction - Building embed with 5 fields
[INFO] openclaw:discord:interaction - Replying to interaction with embed
[DEBUG] openclaw:discord:interaction - Response sent: 200 OK

Exit Code Verification

# After running verification tests
echo $?
# Expected: 0 (success)

โš ๏ธ Common Pitfalls

Environment-Specific Traps

  • WSL2 Timing Issues: WSL2 clock sync can cause interaction response timeouts. Discord interactions require responses within 3 seconds. Use ntpd or wsl2-hibernate workaround.
  • Docker Container Timeouts: If running in Docker, ensure the container clock matches host. Run docker run --cap-add=SYS_TIME or sync with timedatectl set-ntp true.
  • Windows Defender Firewall: May block WebSocket connections in DM contexts. Add exception for Discord's gateway IPs.

Configuration Missteps

  • Missing Intents: Without Guilds intent, DM interactions may not register properly
  • Ephemeral Default: Some configurations default to ephemeral: true, which can cause "Done." to appear in unexpected locations
  • Stale Cache: Old command definitions cached locally may override registration updates

Handler Anti-Patterns

  • Not Awaiting Async Calls:
    // Wrong
    interaction.deferReply();
    fetchStatusData().then(data => {
        interaction.editReply({ embeds: [data] });  // 'this' context lost
    });
    

    // Correct await interaction.deferReply(); const data = await fetchStatusData(); await interaction.editReply({ embeds: [data] });

  • Swallowed Exceptions: Empty catch blocks prevent debugging
    // Wrong
    try { ... } catch (e) {}
    

    // Correct try { … } catch (e) { console.error(‘Status command failed:’, e); throw e; // or handle gracefully }

  • Race Conditions: Multiple rapid command invocations may conflict with shared state

Model/Provider Edge Cases

  • Opus 4.6 Specific: Some data fields may be null when model context is cold, causing embed building to fail silently
  • Rate Limiting: Discord DM interactions have stricter rate limits; ensure request debouncing

Evidence & Sources

This troubleshooting guide was automatically synthesized by the FixClaw Intelligence Pipeline from community discussions.