Skip to content

Encrypted attachment sending fails on physical iOS devices with RoomError.InvalidAttachmentData, but works reliably in the Simulator #55

Description

@labadmin001

Here's the cleaned-up bug report, ready to file:


[BUG] Encrypted attachment sending fails on physical iOS devices with RoomError.InvalidAttachmentData, but works reliably in the Simulator

Environment

  • @unomed/react-native-matrix-sdk: 0.9.1 (latest published)
  • React Native 0.81.5, Expo SDK ~54.0.34
  • Physical devices (both affected): iPhone 15 Pro Max, iPhone XR — iOS 26.5.2
  • Simulator: works correctly — same SDK version, same app code
  • Homeserver: Synapse 1.156.0, MSC4186 confirmed working, max_upload_size confirmed 50 MB

Summary

Every call to timeline.sendFile() / timeline.sendVoiceMessage() inside a genuinely encrypted room throws RoomError.InvalidAttachmentData on real devices. Same SDK, same room type — works reliably in the Simulator (3 consecutive clean passes). Text messages work correctly on physical devices in the same rooms, so this is specific to attachments, not encryption or connectivity.

Reproduction

Create an E2EE room, confirm membership, then attempt to send a file, video, or voice message. Fails every time on device (2 devices tested), succeeds every time in the Simulator. Reproduced across multiple fresh identity pairs, multiple formats (HEIC/JPEG/PNG, MP4/MOV, M4A), and a range of file sizes.

Ruled out, with evidence

  1. File validity/existence — confirmed present and correctly sized at call time.
  2. Missing/incorrect metadata — tried both omitting and supplying metadata explicitly; same failure.
  3. Upload mechanism — both UploadSource.File and UploadSource.Data (raw bytes) fail identically.
  4. Server upload limit — the SDK's own max_upload_size pre-flight check passes every time (returns 50 MB, matching our real server limit).
  5. Rust-level tracing — run at maximum verbosity, the SDK's own tracer shows the text send path working clearly, but produces zero output anywhere for the attachment code path.
  6. Physical-device stackshots — captured with a symbolicated build (first time we achieved real function name resolution). Every SDK runtime thread was idle at capture time; the failure resolves too quickly to catch reliably with a manually-timed snapshot. Flagged honestly — this is not evidence either way.

Conclusion

Given that maximum-verbosity tracing shows nothing for this failure while the identical infrastructure clearly works for text, the rejection most likely occurs in the FFI/native binding glue layer itself — below what the SDK's Rust-side tracing can see into from JS/TypeScript.

Questions for maintainers

  • Is there a known Simulator-vs-device divergence in the attachment FFI path?
  • Is any lower-level Swift-side logging available for the binding layer?
  • Can InvalidAttachmentData ever be thrown directly from the binding layer, before reaching Rust? This seems the most likely explanation given the evidence above.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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