Skip to content

Android host-path Markdown image is blank while desktop and HTTPS embeds work #10322

Description

@andybergon

Environment

  • Android app: 1.0.3, reported by the user.
  • Connected server: 0.0.39-nightly.20260906.1292 on macOS arm64, verified through its environment endpoint after the screenshots were captured.
  • Provider: Codex.

Reproduction

  1. Have Codex embed a PNG stored on the connected host, outside the thread's project, using an absolute-path Markdown image.
  2. Open the same thread and assistant message on desktop and Android.
  3. Embed the same PNG through a reachable private HTTPS URL as a control.

Emitted Markdown, with the private path replaced by an equivalent example:

![Mobile PNG test](</Users/example/assets/test.png>)

The tested file is a valid 1800 × 2600 PNG, 5,008,501 bytes.

Observed

  • Desktop renders the host-path image.
  • Android leaves a large blank area at that image, without a visible image or error.
  • Android renders the same PNG when embedded through private HTTPS.

Expected: the authorized host-path image renders on Android too, or a visible error explains why it cannot be loaded.

The HTTPS embed is a verified workaround for this image, but requires separately hosting it. The exact failure layer is unknown. An Android 1.0.4 emulator rendered an in-project copy, so that test differs in both client version and path scope and does not establish a regression or fix for the phone case.

Related: #9094 was closed after the local-path and native-image fixes, with a request to open a new issue for remaining failures. This report concerns a host-path Markdown image on Android, not a data URI or HTML image.

Activity

  1. juliusmarminge commented on Sep 6, 2026

    @juliusmarminge
    Member

    Triage

    Confirmed as a new Android bug, not a re-open of #9094. Desktop rendering plus a working HTTPS control isolate this to host-path Markdown → signed environment asset → Android image view, not “PNG is bad” or “Android cannot show images.”

    What the clients do today

    ![Mobile PNG test](</Users/example/assets/test.png>) is classified as a host file (packages/client-runtime/src/markdownImages.ts; angle brackets are stripped). Current main asks for a media-file signed URL (#9023, apps/server/src/assets/AssetAccess.ts). That grant is allowed: projects are not a filesystem sandbox (docs/internals/environment-auth.md). Desktop chat uses the same resource via ChatMarkdownAssetImage and paints.

    Android chat goes through ThreadFeed.renderMarkdownImage → ThreadMarkdownImage (apps/mobile/src/features/threads/). The tile uses React Native Image at opacity 0 until onLoad. #10199 sizes that tile from the server header (this fixture is 1800×2600), so a failed or hung decode looks like a large blank rather than a missing node. If renderImage returns null, NativeMarkdownImage loads the raw host path as a URI — another empty rounded box with no error.

    Store 1.0.3 may still be on the older #6433 workspace-file request, which cannot authorize a path outside the project. That should show “Image unavailable”; a silent loading/fallback box would match this report. The 1.0.4 emulator in-project copy does not answer the phone case (different version and path scope).

    HTTPS works because it is Direct and never hits the host-file signer.

    Related: #9023 (host media), #6433 (workspace images), #8779 (Android markdown renderer), #10199 (frame-before-bytes), open #9087 (iPhone empty gray boxes — similar loader, different platform).

    Suggested check (before a fix PR)

    On 1.0.4 / current, same thread, same absolute dest (not an in-project copy):

    1. Does the host-path image paint?
    2. Does an in-project relative embed paint on that same phone?
    3. Does a tiny PNG at the same absolute path paint (rules out the 5 MB / tall decode)?

    If current still blanks: keep the signed media-file URL, make the Android tile use a loader that reports failure (expo-image is already the #9087 direction), and never leave a reserved frame with no image and no “Image unavailable.”

    Not duplicate / invalid / wontfix. HTTPS hosting remains a workaround.

  2. added
    via-triageFiled through npx t3 triage
    bugSomething is broken or behaving incorrectly.
    on Sep 6, 2026
  3. andybergon commented on Sep 6, 2026

    @andybergon
    Author

    Retested on the same phone with Android 1.0.4 built from d924fe266. The original image now renders in its original thread and message. The absolute-path embed, identical in-project relative copy, and tiny PNG at a separate outside-project path also render. I can no longer reproduce this on the current build.

    Could you publish a new Google Play release too, so we can get these fixes without sideloading?

  4. shivamhwp commented on Sep 7, 2026

    @shivamhwp
    Collaborator

    Note: GPT-6 on behalf of Shivam (@shivamhwp).

    Closing based on your successful retest on the same Android phone using 1.0.4 at d924fe2. The original image and thread, an in-project relative copy, and a tiny image outside the project all rendered. Google Play rollout is a separate follow-up; this closure reflects the confirmed fix in that tested build.

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