Skip to content

[Bug]: iOS app sends an image-only message without the attachment-only prompt the desktop adds #14049

Closed

Description

@Vantrongs

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/mobile

Steps to reproduce

  1. In the iOS app, attach an image and send it with no text.
  2. Do the same in the desktop app.

Expected behavior

Both clients send the same turn. The desktop sends [User attached one or more files without additional text. Respond using the conversation context and the attached files.] as the text.

Actual behavior

The iOS app sends only the image reference, for example ![IMG_4039.jpeg](t3-context://v1/image/…). The agent receives the image and the server's [Attached image "…" is saved at: …] line, but no instruction for an image-only turn.

Likely cause

ATTACHMENT_ONLY_BOOTSTRAP_PROMPT is defined in apps/web/src/components/chat/composerPromptHistory.ts and applied only by the web client (ChatView.tsx, sendQueuedMessage.ts). The iOS outbox sends the composer text unchanged through serializeComposerMessageForServer (apps/mobile/src/lib/composerContext.ts, called from use-thread-outbox-drain.ts).

Suggested fix

Move the constant to packages/shared, and in the iOS app use it when the text has nothing but attachment references.

Impact

Minor bug or occasional failure

Version or commit

iOS app 1.3.0 (85); desktop server 0.0.43-nightly.20260926.2282; main @ 94f92a7

Environment

iPhone, connected through the T3 Connect relay; provider Claude (Opus 5.5)

Logs or stack traces

Screenshots, recordings, or supporting files

No response

Workaround

No response

Activity

  1. added
    bugSomething is broken or behaving incorrectly.
    needs-triageIssue needs maintainer review and initial categorization.
    on Sep 28, 2026
  2. juliusmarminge commented on Sep 28, 2026

    @juliusmarminge
    Member

    Triage

    Confirmed on current main. This is a real client mismatch, and it is not fixed by a newer server. The desktop app is the web client. An image added to an empty composer stays on the shelf and is not inserted as a chip (imageAttachmentsGetChips in ChatComposer.tsx is false when the prompt has no prose). Send then substitutes an empty prompt with ATTACHMENT_ONLY_BOOTSTRAP_PROMPT in both ChatView.tsx and sendQueuedMessage.ts:

    [User attached one or more files without additional text. Respond using the conversation context and the attached files.]

    The mobile app always inserts an inline image reference (appendComposerDraftAttachments(..., { appendReference: true }) from photo pick and paste in use-thread-composer-state.ts, and the same option in the new-task composer). The outbox then sends queuedMessage.text unchanged from both drain paths in use-thread-outbox-drain.ts (serializeComposerMessageForServer around the existing-thread startTurn and the new-thread buildProjectThreadStartTurnInput). There is no bootstrap constant under apps/mobile.

    The image is not dropped. The server still attaches the bytes and appends [Attached image "…" is saved at: …]. Because the text is ![IMG_4039.jpeg](t3-context://v1/image/…), projectComposerContextForProvider also turns that into an [Image: …; ref=…] marker plus a t3_context envelope (name, mime type, size, attachment id). What the provider does not get is the instruction to respond. The same React Native path covers Android, not only iOS 1.3.0.

    The suggested shared constant is right (packages/shared, so web prompt-recall can keep treating that sentence as non-user text). Do not substitute it for every attachment-only reference. Web still sends file-only messages as the file chip; only image-only messages with no prose become the bootstrap. Limit the mobile swap to text that is nothing but image references, and apply it on both outbox dispatch paths so the stored turn matches desktop. No existing issue covers this.

  3. added
    via-triageFiled through npx t3 triage
    and removed
    needs-triageIssue needs maintainer review and initial categorization.
    on Sep 28, 2026
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

    bugSomething is broken or behaving incorrectly.via-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions