Skip to content

Slack file uploads not persisted to session media directory #66

Description

@Aaronontheweb

Problem

User-uploaded images via Slack aren't being properly captured and persisted to the session media directory.

Fix Attempt #1 (Commit 0c6b60f) - Still Broken

What Was Supposedly Fixed

PR #66 claimed to fix "Slack file uploads not persisted to session media directory" by fixing 5 bugs in the inbound Slack pipeline:

  1. Handle(AppMention) created SlackInboundMessage without mapping files
  2. MapSlackFiles silently skipped files missing UrlPrivateDownload with no fallback to UrlPrivate
  3. SlackRoutingPolicy rejected file-only messages (no text)
  4. SlackConversationActor dropped messages with empty normalized text even when files were attached
  5. Added proper file handling in the message routing path

Commit: 0c6b60f "Fix Slack file uploads not persisted to session media directory (#66)"
Date: Feb 28, 2026
Files Changed:

  • src/Netclaw.Channels/SlackActorHierarchyTests.cs (69 lines)
  • src/Netclaw.Channels/SlackRoutingPolicyTests.cs (70 lines)
  • src/Netclaw.Channels/Slack/SlackChannel.cs (10 lines)
  • src/Netclaw.Channels/Slack/SlackConversationActor.cs (4 lines)
  • src/Netclaw.Channels/Slack/SlackRoutingPolicy.cs (4 lines)

Reality After Fix Was Applied

Session Directory: /tmp/netclaw-sessions/C0AGM484P0Q_1772316008_409379/

File Source Status
feedly-icon.png Web fetch (downloaded) ✅ Working
media/avatar.png curl download ✅ Working
media/netclaw-logo.png curl download ✅ Working
Slack-uploaded images Slack file upload NOT PRESENT

Key Finding

  • Manually downloaded images work (web fetch, curl, shell download)
  • Slack file uploads don't work (user uploads in Slack are not saved to session media directory)

Impact:

  • I cannot send you images (multimodal output broken)
  • You cannot send me images (multimodal input broken)
  • Both sides of the multimodal pipeline are broken

Code Analysis

What We Found

  1. MapSlackFiles has no logging - We can't see if files are being extracted
  2. Handle(MessageEvent) has no logging - We can't see if messages with files are being processed
  3. SlackConversationActor silently drops messages - Line 86: "Ignoring Slack event... no files" but we can't verify if files were actually found

Root Cause Hypothesis

The fix may have addressed code paths that aren't being triggered in production, or the Slack API is returning files in a different format than expected.

Likely issue: f.UrlPrivateDownload ?? f.UrlPrivate returns null for uploaded images, so they're silently skipped in MapSlackFiles.

Evidence This Is STILL BROKEN

Test Scenario

  1. Upload an image file in Slack
  2. Image should be saved to session-media/ directory
  3. AI should receive the image in message context
  4. AI should be able to reference/display the image

Actual Result

  • Images uploaded in Slack are not appearing in session directory
  • No session-media/ entries for Slack-uploaded files
  • AI cannot see or reference uploaded images

Logging Added (Feb 28, 2026)

To help debug this, I added comprehensive logging to SlackChannel.cs:

// In Handle(MessageEvent):
if (files is not null && files.Count > 0)
{
    _logger.LogInformation("Received Slack message with {FileCount} file(s) - EventId: {EventId}, Channel: {ChannelId}",
        files.Count, slackEvent.Ts, channelId.Value);
    
    foreach (var file in files)
    {
        _logger.LogInformation("  - File: {Name} (Id: {Id}, Type: {MimeType}, Size: {Size} bytes)",
            file.Name, file.Id, file.MimeType, file.Size ?? 0);
    }
}

// In MapSlackFiles:
_logger?.LogDebug("Processing {FileCount} Slack files", files.Count);
_logger?.LogDebug("Skipping file '{Name}' - no download URL available");
_logger?.LogDebug("Found download URL for file '{Name}' - {Url}");
_logger?.LogDebug("Processed {Count} Slack files (filtered from {Total})", count, files.Count);

Next Step: Restart Netclaw and check the logs when uploading an image in Slack. Look for:

  • Does "Received Slack message with X file(s)" appear?
  • If yes, what files are listed?
  • If no, the file upload isn't reaching Handle(MessageEvent) at all
  • Check if "Skipping file - no download URL available" appears (indicates URL extraction failure)

Related Issues

Priority

CRITICAL - This breaks the core multimodal capability that was just implemented. Both user→assistant and assistant→user image flows are broken.

Timeline

  • Issue filed: Feb 28, 2026 (before fix commit)
  • Fix committed: 0c6b60f (Feb 28, 2026)
  • Re-verified broken: Feb 28, 2026 (after fix)
  • Logging added: Feb 28, 2026
  • Status: Still open, still broken

Suggested Investigation Path

  1. Check if files reach MapSlackFiles - Add logging before the loop
  2. Check what URLs are available - Log UrlPrivateDownload, UrlPrivate, ShareUrl from Slack API response
  3. Trace the full flow - File uploaded → Slack webhook → SlackChannel.HandleSlackGatewayActorSlackConversationActor → SessionMediaService
  4. Verify session-media persistence - Add logging when files are written to disk
  5. Check AI message context - Verify DataContent is added to chat history after file download

Expected log output when upload works:

Received Slack message with 1 file(s) - EventId: 1709234567.890123, Channel: C0123456789
  - File: screenshot.png (Id: F12345678, Type: image/png, Size: 142356 bytes)
Processing 1 Slack files
Found download URL for file screenshot.png - https://files.slack.com/files-pri/T01234567-F12345678...
Processed 1 Slack files (filtered from 1)
[SessionMediaService] Downloading file: screenshot.png to session-media/
[ChatMessageConverter] Added DataContent reference to chat history

If you see logs but no files in session directory, the issue is in the download/persistence step. If you don't see the "Received Slack message" log, the issue is earlier in the pipeline.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions