Realtime Voice list_projects returns a project ID that create_thread immediately rejects

Open 💬 1 comment Opened Aug 8, 2026 by alexj11324
💡 Likely answer: A maintainer (github-actions[bot], contributor) responded on this thread — see the highlighted reply below.

What version of the Codex App are you using?

  • ChatGPT/Codex desktop app: 26.803.41515
  • Bundle build: 6321
  • Bundled Codex CLI: 0.147.0-alpha.6.5

What platform is your computer?

macOS 27.0 (26A5388g), Apple silicon (arm64).

What issue are you seeing?

In a Realtime Voice coordinator thread, codex_app.list_projects returns a saved local project using the legacy/remote-shaped schema:

{
  "schemaVersion": 1,
  "projects": [{
    "projectKind": "remote",
    "hostId": "slingshot:env_<redacted>",
    "hostDisplayName": "Mac",
    "path": "/Users/<user>/path/to/project",
    "projectId": "base64(slingshot:env_<redacted> + newline + path)",
    "supportsWorktrees": true
  }]
}

Calling codex_app.create_thread seconds later with that exact projectId fails immediately:

Unknown projectId: <same ID>. Call list_projects to find available projects.

This is reproducible with both environment: {type: "worktree"} and environment: {type: "local"}. A no-op retry with the same just-returned ID also fails and creates no threadId or clientThreadId.

On the same Mac, account, app process, and saved project, a normal local Codex task sees a different project protocol:

{
  "schemaVersion": 2,
  "projects": [{
    "projectKind": "local",
    "hostId": "local",
    "projectId": "<persistent UUID>",
    "path": "/Users/<user>/path/to/project",
    "isGitRepository": true
  }]
}

Using that v2 UUID with create_thread works. Three consecutive direct worktree creations succeeded (3/3), produced three independent clean worktrees, and resolved to the same Git HEAD. No fork was used.

The saved project is healthy in Desktop state: local-projects, project-order, selected-project, and existing thread-project-assignments all consistently use the v2 UUID. remote-projects does not contain this project. The env_<redacted> value still exists as electron-local-remote-control-environment-id, which appears to be where the Voice/slingshot catalog identity originates.

Projectless create_thread succeeds from the affected Voice thread. Forking an existing project thread also succeeds. The failure is specific to direct project creation using the ID returned by Voice's own list_projects result.

Minimal reproduction

  1. Start or resume a Realtime Voice conversation connected to the local Mac Codex host.
  2. Call codex_app.list_projects.
  3. Select an already-saved local Git project from the returned list.
  4. Copy its returned projectId byte-for-byte.
  5. Call codex_app.create_thread with:
{
  "target": {
    "type": "project",
    "projectId": "<exact value from step 2>",
    "environment": {"type": "worktree"}
  },
  "prompt": "No-op verification only"
}
  1. Observe Unknown projectId immediately.
  2. In a normal local Codex task, repeat steps 2-5. Observe that list_projects returns schema v2/local UUIDs and create_thread succeeds.

Sanitized timing evidence

UTC, same Voice turn:

| Time | Observation |
|---|---|
| 22:29:11.760 | Voice rollout records list_projects returning schema v1, projectKind=remote, hostId=slingshot:env_<redacted>. |
| 22:29:33.179 | create_thread with that exact ID returns Unknown projectId in 0.1 seconds. |
| 22:29:51.932 | Same ID with local environment fails identically. |
| 22:35:25.705 | A fresh Voice list_projects call again returns schema v1/slingshot IDs. |
| 22:35:33.557 | Immediate no-op direct-project retry fails identically. |

The Desktop log in the same window shows the local project catalog returning schema v2 UUIDs, while the Voice rollout records schema v1 slingshot IDs. This strongly suggests that project discovery and project creation are being serviced by different host/catalog routes, or that the Voice bridge is projecting a v1 remote catalog while create_thread validates against the Desktop v2 registry.

Expected behavior

  • Every projectId returned by list_projects must be accepted by create_thread for the same caller while the project remains available.
  • list_projects and create_thread must resolve through one authoritative project registry/host route.
  • If a v1 slingshot ID must be translated to a v2 local UUID, the bridge should perform that translation before returning the ID or before validation.
  • The error should include the registry/host/schema mismatch when translation is impossible, rather than calling the just-returned ID unknown.

Actual behavior

  • Voice receives a valid-looking saved-project entry in schema v1.
  • create_thread rejects its exact ID against a different registry.
  • The same physical saved project works 3/3 from the schema v2 local route.
  • Projectless creation and forking work, so this is not a general app-server, repository, Git, worktree, or permissions failure.

Suggested regression coverage

Add an integration test for Realtime Voice/Remote Control in which:

  1. list_projects returns a saved project for a connected local host.
  2. The returned ID is passed unchanged to create_thread for both local and worktree environments.
  3. Creation succeeds and the resulting task is assigned to the same canonical project.
  4. The test fails if discovery returns a v1 slingshot ID while creation validates only the v2 UUID namespace.

It would also help to log a request-scoped catalogSchemaVersion, resolved host ID, and canonical project ID at both dynamic-tool boundaries.

Related issues (related, but not duplicates)

  • #36404 covers Realtime Voice losing task-tool handlers/live host routing after delegation, generally yielding missing-handler or generic failures. This report is the narrower deterministic list_projects/create_thread project-ID contract mismatch with Unknown projectId.
  • #35894 covers dynamic-tool response arbitration across subscribers. It may be relevant to routing, but does not cover split project ID namespaces.
  • #26907 covers remote-started threads missing or being refused codex_app tools. Here both tools are present and callable; their results disagree.
  • #25498 covers unknown IDs for unregistered projects or missing project discovery. Here the project is already saved and the failing ID was returned immediately by list_projects.

Privacy note

Project name, username, absolute private path, environment ID, project UUID, thread IDs, prompts, account identifiers, and unrelated project metadata are intentionally redacted. Narrow raw logs can be provided privately through an OpenAI-controlled channel.

View original on GitHub ↗

1 Comment

github-actions[bot] contributor · 19 days ago

Potential duplicates detected. Please review them and close your issue if it is a duplicate.

  • #36592

Powered by Codex Action