Skip to content

fix: persist errorMessage on non-throwing turn failure and shorten summary (fixes #757) - #763

Open
Soumya95 wants to merge 1 commit into
openai:mainfrom
Soumya95:fix/error-message-on-failed-turn
Open

Soumya95 wants to merge 1 commit into
openai:mainfrom
Soumya95:fix/error-message-on-failed-turn

Conversation

@Soumya95

Copy link
Copy Markdown

Summary

Fixes #757: a server-side turn failure that completes normally stored no errorMessage anywhere, so status showed only Summary: { — the first line of the pretty-printed JSON error body.

Two independent gaps caused this:

  1. errorMessage was only written on the throwing path. tracked-jobs.mjs set errorMessage inside the catch block. A turn that failed with exitStatus != 0 but completed normally ran through the success branch — no errorMessage was ever stored, and renderJobStatusReport fell through to "No captured result payload was stored."

  2. The summary took the first line of raw output. firstMeaningfulLine(rawOutput, ...) picked { when rawOutput was a pretty-printed error body. The Codex error: progress line (codex.mjs:539) similarly output the error body without truncation.

Changes

plugins/codex/scripts/lib/tracked-jobs.mjs

  • On the success branch, read execution.errorMessage and persist it to both the job file and the index row when completionStatus === "failed".

plugins/codex/scripts/codex-companion.mjs

  • executeTaskRun: surface result.error.message as errorMessage; prefer failureMessage over rawOutput for the summary; pass through shorten().
  • Review paths (structured and adversarial): add errorMessage and pass summary through shorten(), so multi-line JSON bodies can never reduce to punctuation.

plugins/codex/scripts/lib/codex.mjs

  • Shorten the Codex error: progress line via shorten(message.params.error.message, 96).

tests/state.test.mjs

  • Two regression tests:
    • Non-throwing failed execution persists errorMessage in job file and index.
    • Completed execution stores no meaningful errorMessage.

Verification

All 93 tests pass: node --test tests/*.test.mjs — 0 failures.

…mmary (openai#757)

Two gaps combined to make server-side turn failures illegible in status:

1. errorMessage was only written in the catch path, so a turn that failed
   with exitStatus != 0 but completed normally stored no reason anywhere
   reachable from 'status'.

2. The summary took the first line of the pretty-printed error body,
   which is a bare opening brace.

Now:
- tracked-jobs.mjs reads execution.errorMessage on the success branch and
  writes it to both the job file and the index when failed.
- codex-companion.mjs task/review paths surface result.error.message as
  errorMessage and prefer it over rawOutput for the summary.
- Summary and Codex error: progress line are passed through shorten() so
  multi-line JSON bodies cannot reduce to punctuation.
- Regressions covered by two new state.test.mjs tests.
@Soumya95
Soumya95 requested a review from a team September 14, 2026 07:37

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 362975882f

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

status: result.status,
failureMessage: result.error?.message ?? result.stderr
});
const failureMessage = result.error?.message ?? result.stderr ?? parsed.parseError ?? "";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve parse errors when stderr is empty

When an adversarial review returns malformed structured output without an app-server error, result.stderr is normally the empty string, which is non-nullish and therefore prevents parsed.parseError from being selected here. The subsequent summary falls back to the malformed response's first line (often just {), regressing the previous behavior that surfaced the JSON parse error and recreating the unhelpful status summary this change is intended to fix. Treat an empty stderr value as absent before falling back to parsed.parseError.

Useful? React with 👍 / 👎.

payload,
rendered,
summary: firstMeaningfulLine(result.reviewText, `${reviewName} completed.`),
summary: shorten(firstMeaningfulLine(result.reviewText, `${reviewName} completed.`), 96),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Prefer native review errors in failed-job summaries

When a native review/start turn finishes with a nonzero status and an error but produces no review text, this still records the summary as Review completed.; if the review text is a formatted error body, it can still record only {. Because /codex:status renders this indexed summary rather than errorMessage, failed native reviews continue to show a misleading or meaningless summary despite the useful error now being persisted. For failed results, derive the summary from result.error?.message or stderr before considering reviewText.

Useful? React with 👍 / 👎.

Edo771977 pushed a commit to Edo771977/codex-plugin-cc that referenced this pull request Sep 17, 2026
Upstream PR openai#763 (Soumya95), two conflicts resolved.

A turn that failed without throwing (a rejected model, an unsupported
parameter) stored only a truncated summary, so /codex:result showed that the
job failed but not why. The failure text is now persisted as errorMessage on
both the job file and the state index, and summaries are shortened to 96
characters instead of carrying a whole error into an index entry.

Conflicts: both in tests/state.test.mjs and both unions. The import block
keeps the fork's list and adds runTrackedJob. The test block keeps the fork's
tests and appends the PR's two; the conflict cut through the fork's last test
(its closing `});` was the line both sides shared after the marker), so that
brace is restored explicitly in the resolution.

Verified: node --check on the three touched scripts; tests/state.test.mjs,
tests/tracked-jobs.test.mjs and tests/runtime.test.mjs 139/139.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UXfvnjSC72HsM6EEPVt2Tg
Edo771977 pushed a commit to Edo771977/codex-plugin-cc that referenced this pull request Sep 17, 2026
Adds openai#731, openai#737, openai#747 and openai#763 to "Differences From Upstream", and notes in
Requirements that Node no longer has to be on the system PATH now that the
hooks go through scripts/run-node.sh (including CODEX_COMPANION_NODE for
pinning one).

Verified: full npm test 254/254.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UXfvnjSC72HsM6EEPVt2Tg
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A server-side turn failure that terminates stores no errorMessage, so status reports the reason as Summary: {

1 participant