codex - ๐Ÿ’ก(How to fix) Fix Codex Desktop `/goal` ignores auto-created `Pasted text.txt` attachments and treats the goal as empty

Official PRs (โ€ฆ)
ON THIS PAGE

Recommended Tools

ร—6

Utilities matched from this issueโ€™s tags and category โ€” try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful ยท Quick feedback

Loadingโ€ฆ

Codex Desktop converts sufficiently large pasted text into a text-file attachment named Pasted text.txt. That attachment is non-empty on disk and is visible in the composer, but the /goal submit path derives the goal objective only from the visible editor text.

As a result, if the user intends the attached pasted text to be the /goal objective and does not also type the same content into the editor, Codex Desktop handles the command as an empty or missing goal objective. The failure looks like a blank submission even though the composer has a non-empty text attachment.

This is not a model issue and not a backend interpretation issue. In the inspected Desktop build, the client stores pasted text as fileAttachments, while the /goal objective extraction path reads only composer.getText() / promptRaw and never materializes the text-file attachment into the objective before validation.

Error Message

  1. If the expanded objective exceeds the goal length limit, show the existing "goal too long" style validation error. It should not be reported or handled as empty.
  2. If file/text attachments are intentionally unsupported as /goal objective input, block the submit with a specific UI error such as "Text attachments cannot be used as a goal objective; type a short goal or refer to the file by name/path." It should not silently behave like a blank objective. Related but not duplicate: #25144 asks for an option to disable automatic conversion of long pasted prompts into .txt attachments. This issue is narrower and behavioral: once Codex Desktop has already converted a large paste into Pasted text.txt, that non-empty text must not be treated as an empty /goal objective without a specific error.
  • reject it before submission with a specific "text attachments cannot be used as goal objectives" error.
  • Expected: either the attached text is materialized and validated, or a specific unsupported-attachment error appears.
  • Expected if materialization is supported: goal-length validation error.

Root Cause

  • The UI shows non-empty user content, but the command path behaves like the input is blank.
  • Long goals/prompts are exactly the case where users are most likely to hit automatic pasted-text attachment conversion.
  • The failure mode gives the wrong diagnosis. It looks like the user submitted whitespace, but the pasted text exists on disk and is attached.
  • Users may repeatedly retry or lose time because no message explains that Pasted text.txt is not considered a /goal objective.
  • It creates inconsistent behavior between Codex clients: the public TUI expands pending large-paste content for /goal, while Desktop does not.

Fix Action

Workaround

For now, the reliable workaround is to type a short goal objective directly in the editor and refer to the attached file by name/path, for example:

/goal follow the instructions in the attached Pasted text.txt

That workaround is not obvious from the UI, and it does not fix the core issue that the automatic pasted-text attachment is silently ignored by the /goal objective extractor.

Code Example

%USERPROFILE%\.codex\attachments\pasted-text-attachments.json

---

f19a18da-088e-4280-84b6-fdc3c940f3b9\pasted-text.txt  14963 bytes
f0a64c46-0e40-4d2c-abe9-fef76796360a\pasted-text.txt  11012 bytes
8adae7d1-9b28-418e-8622-847e10660ab6\pasted-text.txt  14963 bytes
5282069a-3f13-4dbb-8119-bf4a2d372c3a\pasted-text.txt  28029 bytes
e696cf76-45c1-48d1-8107-28df2368fe9b\pasted-text.txt  10161 bytes

---

create-pasted-text-attachment-for-host

---

remove-pasted-text-attachment-for-host

---

pasted-text.txt
pasted-text-attachments.json
attachmentPaths
pendingRemovalPaths

---

promptRaw = composer.getText()

---

input: [{ type: "text", text: prompt, text_elements: [] }, ...images]
fileAttachments: context.fileAttachments

---

input: input
attachments: attachmentsFrom([...fileAttachments, ...addedFiles])

---

# Files mentioned by the user:

---

/goal follow the instructions in the attached Pasted text.txt
RAW_BUFFERClick to expand / collapse

Summary

Codex Desktop converts sufficiently large pasted text into a text-file attachment named Pasted text.txt. That attachment is non-empty on disk and is visible in the composer, but the /goal submit path derives the goal objective only from the visible editor text.

As a result, if the user intends the attached pasted text to be the /goal objective and does not also type the same content into the editor, Codex Desktop handles the command as an empty or missing goal objective. The failure looks like a blank submission even though the composer has a non-empty text attachment.

This is not a model issue and not a backend interpretation issue. In the inspected Desktop build, the client stores pasted text as fileAttachments, while the /goal objective extraction path reads only composer.getText() / promptRaw and never materializes the text-file attachment into the objective before validation.

Environment

  • Product: Codex Desktop
  • OS: Windows 11 Pro, x64, build 26200
  • Codex Desktop package: OpenAI.Codex_26.527.3686.0_x64__2p2nqsd0c76g0
  • Codex Desktop version: 26.527.3686.0
  • Installed app bundle SHA-256 for app.asar: 51D9C84D8C51D51A71E1EA05FA0521DB3225E68914FED680CD64960A4B7A745A
  • Public repository revision inspected for protocol/TUI comparison: openai/codex@3e7baa00e43419967d90d6ad9cef40f58d5ac89f
  • Date observed: 2026-05-30 / 2026-05-31 JST

Reproduction

  1. Open Codex Desktop on Windows.
  2. Start a thread or open an existing thread.
  3. Paste a long non-empty text block into the composer, large enough for Desktop to convert it into a text attachment.
    • In this build, the UI/RPC path labels this file as Pasted text.txt.
  4. Use /goal or activate goal mode with the pasted text attachment intended to be the goal objective.
  5. Do not manually type the full pasted text into the visible editor. The visible editor text is empty or contains only the /goal command/prefix.
  6. Submit.

Expected behavior

Codex should not treat a non-empty pasted-text attachment as an empty goal submission.

One of these behaviors would be acceptable:

  1. Expand/materialize the Pasted text.txt payload into the /goal objective before goal validation, the same way the TUI expands pending large-paste placeholders before submit and before /goal length validation.
  2. If the expanded objective exceeds the goal length limit, show the existing "goal too long" style validation error. It should not be reported or handled as empty.
  3. If file/text attachments are intentionally unsupported as /goal objective input, block the submit with a specific UI error such as "Text attachments cannot be used as a goal objective; type a short goal or refer to the file by name/path." It should not silently behave like a blank objective.

This report is not asking for /goal to bypass the objective length limit. It is asking for non-empty pasted text not to disappear from the goal-validation path as if it were whitespace.

Actual behavior

The composer has a non-empty Pasted text.txt attachment, but /goal behaves as though the objective is empty or missing when the visible editor text is empty/only the command prefix.

Local state confirmed that the attachments were real files and not empty UI shells. The Desktop app recorded pasted-text attachment paths under:

%USERPROFILE%\.codex\attachments\pasted-text-attachments.json

The recorded attachment files existed and had non-zero sizes, for example:

f19a18da-088e-4280-84b6-fdc3c940f3b9\pasted-text.txt  14963 bytes
f0a64c46-0e40-4d2c-abe9-fef76796360a\pasted-text.txt  11012 bytes
8adae7d1-9b28-418e-8622-847e10660ab6\pasted-text.txt  14963 bytes
5282069a-3f13-4dbb-8119-bf4a2d372c3a\pasted-text.txt  28029 bytes
e696cf76-45c1-48d1-8107-28df2368fe9b\pasted-text.txt  10161 bytes

The problem is therefore not that the pasted text was empty, missing on disk, or failed to be written. The problem is that the Desktop /goal submit path does not read that attachment when computing the goal objective.

Root cause confirmed in Codex Desktop 26.527.3686.0

I inspected the installed Desktop webview bundle from the package listed above. The identifiers below are from the minified bundle, so function names may not be stable between builds, but the data flow is clear in this build.

Desktop bundle evidence locations:

  • composer-Beu4UAMC.js: pasted-text attachment creation, submit-block predicate, /goal objective handling, and local turn start-params construction.
  • app-server-manager-signals-Bpaj8VHp.js: prompt/context text construction and user-message display parsing.
  • composer-view-state-CuoA48W8.js: persisted composer state shape, including pendingThreadGoalObjective and fileAttachments.
  • build-start-conversation-params-NLWgpXGB.js: input and attachments are kept as separate fields when building thread-start params.

1. Large pasted text is converted into a file attachment

In composer-Beu4UAMC.js, the pasted-text handler creates a Pasted text.txt attachment through the RPC method:

create-pasted-text-attachment-for-host

The handler then appends the returned object to fileAttachments. Removal uses:

remove-pasted-text-attachment-for-host

This means Desktop does not keep the full large paste as ordinary editor text. It writes the paste as an attachment and tracks it in composer attachment state.

In app-server-manager-signals-Bpaj8VHp.js, the pasted-text attachment manager writes real files named pasted-text.txt under the Codex attachments directory and records them in pasted-text-attachments.json. The bundle contains the constants and registry shape:

pasted-text.txt
pasted-text-attachments.json
attachmentPaths
pendingRemovalPaths

The local files I inspected were non-empty UTF-8 text files, so the bug is not an attachment-write failure or empty file.

2. The normal submit-block predicate counts fileAttachments as message content

The same Desktop composer computes a message-content predicate from multiple sources. Completed fileAttachments are included in that predicate, while pending file creation blocks submission as file-uploads.

That explains the confusing UI state: the composer can visibly contain content and may be considered non-empty for the general submit button because a file attachment exists.

However, "has message content" is not the same as "has a /goal objective." The goal path below uses a separate objective extraction step.

3. /goal objective extraction only reads the visible editor text

The Desktop submit handler computes the raw prompt from the editor text, effectively:

promptRaw = composer.getText()

It then calls the goal handling function with that promptRaw. The goal function:

  • extracts the objective from /goal ... text when the slash command is present,
  • falls back to the raw editor text when goal mode is active,
  • trims the result,
  • treats zero-length output as an empty goal objective,
  • sets pendingThreadGoalObjective to an empty string and clears the editor in that empty-objective branch.

There is no corresponding step that reads fileAttachments, opens Pasted text.txt, or expands that attachment into promptRaw before goal parsing.

Therefore, when the visible editor text is empty or only /goal without a typed argument, the objective is empty even if the attached pasted text file contains thousands of characters.

4. Turn construction keeps prompt text and file attachments separate

The Desktop start-params builder creates a text input from the prompt string and sends file attachments separately. In the inspected bundle, the shape is:

input: [{ type: "text", text: prompt, text_elements: [] }, ...images]
fileAttachments: context.fileAttachments

The final conversation params builder then maps fileAttachments / added files into the separate attachments field, while leaving input unchanged:

input: input
attachments: attachmentsFrom([...fileAttachments, ...addedFiles])

The prompt-context builder lists attachments under a metadata section titled:

# Files mentioned by the user:

It records attachment labels and paths there, but it does not inline the contents of Pasted text.txt into the prompt text or into threadGoalObjective.

So even after submit, the pasted text attachment is metadata/attachment context, not the actual /goal objective string.

The public goal API also expects the goal objective as a string field, not as an attachment. ThreadGoalSetParams has objective: Option<String>, and the app-server processor trims and validates that string before setting the goal:

5. Public app-server protocol has text/image inputs, not a generic text-attachment input

In the public repository, turn/start documents the turn input list as text or image input:

The public v2 protocol enum similarly contains:

  • Text
  • Image
  • LocalImage
  • Skill
  • Mention

See codex-rs/app-server-protocol/src/protocol/v2/turn.rs lines 268-298.

I did not find a file, textAttachment, or pastedTextAttachment user-input variant in that public protocol enum. That makes it especially important for the Desktop client to decide whether a pasted-text attachment is:

  • expanded into normal Text input,
  • referenced explicitly by path/name in the user's text,
  • or rejected with a targeted UI message for goal-objective use.

Currently, the Desktop /goal path does none of those; it just computes the objective from visible editor text.

Contrast with the public TUI behavior

The public TUI implementation already handles the same conceptual problem differently and correctly for large paste placeholders.

In codex-rs/tui/src/bottom_pane/chat_composer.rs:

  • Large pastes insert a placeholder element into the text buffer.
  • The full paste is stored in pending_pastes.
  • Before submit, prepare_submission_text_with_options expands pending paste placeholders back into the full text.

Relevant public source locations at openai/codex@3e7baa00e43419967d90d6ad9cef40f58d5ac89f:

The TUI /goal path also explicitly counts the expanded pending-paste text before validating the goal length:

There is also a regression test in the public TUI for this exact invariant:

So the public TUI has a clear invariant: a large paste may be represented indirectly in the editor, but it is expanded before submit/goal validation. Codex Desktop breaks that invariant by storing the paste as fileAttachments and not expanding it into the /goal objective path.

Related issue

Related but not duplicate: #25144 asks for an option to disable automatic conversion of long pasted prompts into .txt attachments. This issue is narrower and behavioral: once Codex Desktop has already converted a large paste into Pasted text.txt, that non-empty text must not be treated as an empty /goal objective without a specific error.

Why this matters

  • The UI shows non-empty user content, but the command path behaves like the input is blank.
  • Long goals/prompts are exactly the case where users are most likely to hit automatic pasted-text attachment conversion.
  • The failure mode gives the wrong diagnosis. It looks like the user submitted whitespace, but the pasted text exists on disk and is attached.
  • Users may repeatedly retry or lose time because no message explains that Pasted text.txt is not considered a /goal objective.
  • It creates inconsistent behavior between Codex clients: the public TUI expands pending large-paste content for /goal, while Desktop does not.

Suggested fix

Please make the Desktop /goal path use a single explicit materialization step before goal validation:

  1. Start from visible editor text.
  2. Expand any pending large-paste placeholders.
  3. For Desktop Pasted text.txt attachments created by create-pasted-text-attachment-for-host, either:
    • read and append/materialize the text into the candidate goal objective, then run the normal length validation, or
    • reject it before submission with a specific "text attachments cannot be used as goal objectives" error.
  4. Only after that should the code decide whether the objective is empty, too long, or valid.

More generally, Desktop should separate these predicates:

  • hasComposerContentForSubmitButton
  • hasMaterializedPromptTextForTurn
  • hasGoalObjectiveForGoalCommand

Right now a file attachment can satisfy the first predicate while being invisible to the third predicate.

Suggested regression tests

  1. Paste long non-empty text that Desktop converts into Pasted text.txt, enter /goal with no typed argument, and submit.
    • Expected: either the attached text is materialized and validated, or a specific unsupported-attachment error appears.
    • Not expected: empty-objective handling.
  2. Repeat with attached pasted text below the goal character limit.
    • Expected if materialization is supported: goal is set to the pasted text.
  3. Repeat with attached pasted text over the goal character limit.
    • Expected if materialization is supported: goal-length validation error.
    • Not expected: empty-message / empty-goal handling.
  4. Attach whitespace-only pasted text.
    • Expected: still rejected as empty after materialization/trim.
  5. Attach a normal non-text file and use /goal with no typed objective.
    • Expected: targeted unsupported-attachment message, not silent empty behavior.
  6. Verify normal message submission still treats file attachments according to the intended attachment semantics.
  7. Verify image-only and text-plus-image submission behavior is unchanged.

Workaround

For now, the reliable workaround is to type a short goal objective directly in the editor and refer to the attached file by name/path, for example:

/goal follow the instructions in the attached Pasted text.txt

That workaround is not obvious from the UI, and it does not fix the core issue that the automatic pasted-text attachment is silently ignored by the /goal objective extractor.

Vote matrix ยท Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loadingโ€ฆ

FAQ

Expected behavior

Codex should not treat a non-empty pasted-text attachment as an empty goal submission.

One of these behaviors would be acceptable:

  1. Expand/materialize the Pasted text.txt payload into the /goal objective before goal validation, the same way the TUI expands pending large-paste placeholders before submit and before /goal length validation.
  2. If the expanded objective exceeds the goal length limit, show the existing "goal too long" style validation error. It should not be reported or handled as empty.
  3. If file/text attachments are intentionally unsupported as /goal objective input, block the submit with a specific UI error such as "Text attachments cannot be used as a goal objective; type a short goal or refer to the file by name/path." It should not silently behave like a blank objective.

This report is not asking for /goal to bypass the objective length limit. It is asking for non-empty pasted text not to disappear from the goal-validation path as if it were whitespace.

Still need to ship something?

ร—6

Another batch ranked right after the header list โ€” different links, same matching logic.

Back to top recommendations

TRENDING

codex - ๐Ÿ’ก(How to fix) Fix Codex Desktop `/goal` ignores auto-created `Pasted text.txt` attachments and treats the goal as empty