Skip to content

bug: Codex-generated images display on LAN but not over cellular relay in iOS app #1710

Description

@boeto

What's broken

Codex-generated image outputs are visible in the iOS app when the phone is on the same Wi-Fi/LAN as the desktop daemon, but they are not visible when the phone is on cellular/5G and connects through Paseo relay.

I asked Codex to generate an image:

Generate a rabbit image

Codex completed the turn and the assistant said that the image was generated, but when the iOS app was on cellular/5G, the app only showed text. No image preview/rendered image appeared.

Expected:

  • The generated image should be visible in the iOS app both on LAN and over cellular/relay.
  • If the image is stored on the desktop/daemon side, Paseo should expose it through a mobile/relay-safe image or attachment path.

Actual:

  • The image is visible when the iOS app is on the same Wi-Fi/LAN as the desktop daemon.
  • The image is not visible when the iOS app is on cellular/5G.
  • The image generation itself succeeds locally.
  • The generated PNG exists under ~/.codex/generated_images/....
  • Electron logs repeatedly show:

[attachments] Failed to resolve preview URL [object Object]

This suggests that the current image preview path works with LAN/direct daemon access but is not fully relay-safe.

Steps to reproduce

  1. Open the Paseo desktop app and have the daemon running with relay enabled.

  2. Open the Paseo iOS app while the phone is on the same Wi-Fi/LAN as the desktop daemon.

  3. Start a Codex session.

  4. Ask Codex to generate an image, for example:

    Generate a rabbit image

  5. Confirm that the image is visible on the iOS app while on the same LAN.

  6. Switch the phone to cellular/5G, not the same Wi-Fi/LAN.

  7. Open the same conversation/session in the iOS app through Paseo relay.

Result:

  • The assistant says the image was generated.
  • The image is visible on LAN.
  • The image is not visible over cellular/relay.

Locally, the generated image file exists, for example:

~/.codex/generated_images/019ef6ed-370b-7480-b41a-a625069f189b/ig_06fdd1d3f938738f016a3b1e1342d88193b14c31224b54b58f.png

Where did this happen

iOS app

Paseo version

0.1.98

OS version

Desktop daemon: macOS;Mobile client: iOS app over Wi-Fi/LAN and cellular/5G

Agent provider

Codex

Provider configuration

paseo --version
0.1.98

Sanitized ~/.paseo/config.json:

  {
    "version": 1,
    "daemon": {
      "listen": "0.0.0.0:6767",
      "mcp": {
        "injectIntoAgents": false
      },
      "autoArchiveAfterMerge": false,
      "enableTerminalAgentHooks": false,
      "appendSystemPrompt": "",
      "terminalProfiles": [
        {
          "id": "codex",
          "name": "Codex",
          "command": "omx",
          "args": ["--madmax"],
          "icon": "codex"
        }
      ],
      "cors": {
        "allowedOrigins": ["https://app.paseo.sh"]
      },
      "relay": {
        "enabled": true,
        "endpoint": "xxxxx.net:443",
        "publicEndpoint": "xxxxx.net:443",
        "useTls": true,
        "publicUseTls": true
      },
      "auth": {
        "password": "<redacted>"
      }
    },
    "app": {
      "baseUrl": "https://app.paseo.sh"
    }
  }

Logs

From macOS Electron log:

  ~/Library/Logs/Paseo/main.log

  [2026-06-23 16:31:09.424] [error] [attachments] Failed to resolve preview URL [object Object]
  [2026-06-23 19:36:05.671] [error] [attachments] Failed to resolve preview URL [object Object]
  [2026-06-23 19:36:05.674] [error] [attachments] Failed to resolve preview URL [object Object]

Daemon log did not show relevant attachment/image errors during my check

Screenshots or video

Attached screenshot shows:

  • iOS app on 5G
  • prompt asking Codex to generate a rabbit image
  • assistant says the image was generated
  • no image is rendered
  • Stream end encountered is visible in the conversation

Extra technical context

I looked at the current source code:

  • packages/server/src/server/agent/providers/codex-app-server-agent.ts
  • packages/server/src/server/agent/providers/provider-image-output.ts
  • packages/app/src/components/message.tsx
  • packages/app/src/utils/assistant-image-source.ts
  • packages/app/src/attachments/service.ts

Relevant observations:

  1. Codex image output can be mapped into assistant markdown.

  2. codex-app-server-agent.ts reads image result fields such as path, savedPath, saved_path, url, data, and mimeType.

  3. If Codex returns base64/data image output, Paseo materializes it into a temp directory named paseo-attachments.

  4. renderProviderImageOutputAsAssistantMarkdown() eventually returns markdown like:

    ![Image](<local path or url>)

  5. On the app side, AssistantMarkdownImage resolves non-HTTP/data/blob image sources as file paths and then tries to read them through the daemon/file RPC path.

  6. The generated images I observed were stored outside the workspace, for example under:

    ~/.codex/generated_images/...

    and Codex data-image materialization can also use:

    os.tmpdir()/paseo-attachments/...

These local paths may work while the iOS app can directly reach the desktop daemon on the same LAN, but they do not appear to be reliably resolvable over relay/cellular.

Suggested fix

Short-term fix:

When Codex image output contains a local path / savedPath, the provider should avoid emitting assistant markdown that directly references the local filesystem path.

A small compatibility fix may be to read the local image file in the Codex provider and materialize it as a data:image/...;base64,... URI before calling renderProviderImageOutputAsAssistantMarkdown().

The existing iOS/app renderer already supports data: image sources and persists them through the platform attachment store via persistAttachmentFromDataUrl().

Long-term fix:

A more robust solution would be to represent provider-generated images as relay-safe managed attachments or structured image timeline items instead of local-path markdown images. That would avoid embedding large
base64 payloads in timeline markdown and would better support caching, garbage collection, relay access, and cross-platform rendering.

In short:

  • Short-term: local Codex image path -> data URL before rendering markdown.
  • Long-term: provider image output -> managed attachment / relay-safe image reference.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions