Skip to content

[Bug]: PR description images after captions bypass authenticated media loading without a blank line #26663

Open

Description

@theophanemayaud

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

Problem

An uploaded image disappears from a private GitHub PR description in the iOS app when a caption is immediately above it, with one newline but no blank line. The same description renders correctly on GitHub. Adding one empty line changes which image-loading path T3 uses.

Steps to reproduce

  1. In a private GitHub repository, upload a PNG/JPEG into a PR description with GitHub's editor. Keep the real https://github.com/user-attachments/assets/... URL it produces.

  2. Use this description, replacing UPLOADED_IMAGE_URL with that real attachment URL:

    <sub>Before — overview</sub>
    ![](UPLOADED_IMAGE_URL)
  3. Open the description in T3 Code's iOS PR view. Compare with the same PR on GitHub web.

  4. Add a blank line between caption and image, keeping the image URL unchanged:

    <sub>Before — overview</sub>
    
    ![](UPLOADED_IMAGE_URL)
  5. Reopen/refresh the in-app description. Also test a plain-text caption instead of <sub>; this is not limited to HTML captions or empty alt text.

Expected behavior

The image stays visible and uses T3's authenticated source-control media loading with either spacing. A caption followed by an image on the next line is valid GitHub Markdown.

Actual behavior

Without the blank line, the screenshot is missing in the affected private PR. With the blank line, it takes the custom image renderer path. A screenshot-heavy description can lose every image this way.

Investigation and reproducible results

The agent ran the app's unmodified markdownForNativeRendering and compiled the C++ parser/collector from the exact tarball shipped by main @ 9826dbb9904b2591bfbf60d1317486b59132f56b: react-native-enriched-markdown-1.2.0-t3.16-29ddd424.tgz. Its relevant files were also verified byte-for-byte against fork commit 29ddd424323a9b5313e01b43716a947e6ee62b69.

image only:                 images=1  custom slots=1  placement=root
plain caption + blank line: images=1  custom slots=1  placement=root
plain caption + newline:    images=1  custom slots=0  placement=inline
<sub> caption + blank line: images=1  custom slots=1  placement=root
<sub> caption + newline:    images=1  custom slots=0  placement=inline
<sub> caption on same line: images=1  custom slots=0  placement=inline

For the actual affected private PR description, the same source-level test found 24 images, 0 custom slots. In a local control copy, inserting a blank line after each caption produced 24 images, 24 custom slots, without changing any image URL. No PR was edited for this test.

The agent also checked one affected attachment URL anonymously: HTTP 404. Private PR URLs and image contents are intentionally omitted here. GitHub's POST /markdown endpoint with mode: gfm emits an <img> for the no-blank-line pattern.

The integration gap is in T3's mobile PR renderer:

The key fix appears to be routing all image occurrences, including inline images, through the authenticated PR media resolver. Screenshot sizing with captions should also match the usable GitHub rendering. The fork already exposes resolveImageSource; the PR view does not pass one.

Related: #26662 covers slow opening/zoom/dismissal after tapping an image. This report concerns images missing before they can be opened.

Validation limits

This confirms the normalizer/parser path switch and the anonymous HTTP failure. The missing-image observation comes from the reporter's iPhone. The agent did not run a native iOS UI test because device automation was unavailable.

Impact

Major degradation or frequent failure: an entire visual PR review can appear to have no screenshots.

Version or commit

Source investigated: main @ 9826dbb9904b2591bfbf60d1317486b59132f56b (2026-10-28). Exact affected iOS app version/build not yet recorded.

Environment

T3 Code iOS app on iPhone, private GitHub repository, uploaded user-attachments screenshots. Exact iPhone model/iOS version not yet recorded. The source-level routing gap may affect Android too; no Android UI reproduction is claimed.

Workaround

Add a blank line between each caption and its image, or read the PR on GitHub web. The blank-line change was verified to restore the custom renderer in the parser test; it was not applied to the original PR during this investigation.


Investigated and submitted by the reporter's agent: GPT-6.1 Sol in T3 Code, Codex harness. Device observations are from the reporter; executable parser checks and source analysis are from the agent.

Activity

  1. apratxxm commented on Oct 29, 2026

    @apratxxm

    I have a fix for this and will open a PR shortly. An image on its own line now becomes its own paragraph during mobile Markdown normalization, so it takes the authenticated, full-size image path even with a caption directly above or below. Images inside a line of text stay inline.

  2. davisonio commented on Oct 30, 2026

    @davisonio
    Contributor

    Another way into what looks like the same inline-image path, also in the iOS PR view: several images on one line.

    GitHub's usual side-by-side layout is a row of <img> tags in one paragraph:

    <img src="A.png" width="240"> <img src="B.png" width="240"> <img src="C.png" width="240">

    GitHub shows three 240px images in a row. In the iOS app only the first image in each row renders as an image card; the others render as tiny round thumbnails at text size (the small circles under each card below). The width attribute is dropped too: markdownWithHtml in apps/mobile/src/lib/markdownDocument.ts turns each tag into an inline ![alt](src), so the row becomes one paragraph of inline images.

    Live example: the evidence rows in #27363 (images are public gist URLs, so this one isn't about authenticated media).

    Separately, the cards themselves are cropped at a fixed height (the first card cuts off below "81% left"), which may be intended since tapping opens the full image.

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