Gmail send_email returns JSONDecodeError after successful delivery, causing duplicate emails on retry
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.5k
- PR merge metrics
- PR metrics pending
Description
What version of the Codex App are you using (From “About Codex” dialog)?
26.803.8161.0
Gmail plugin version observed locally: 0.1.8
What subscription do you have?
Pro (Codex desktop app authenticated with a ChatGPT account)
What platform is your computer?
Microsoft Windows NT 10.0.19045.0 x64 (Windows 10 Home, build 19045)
What issue are you seeing?
The Gmail send_email action reports an error even though Gmail has already accepted and sent the message successfully.
The returned tool result is:
JSONDecodeError: Expecting value: line 1 column 1 (char 0)
error_code: UNKNOWN
isError: true
Immediately checking the Gmail Sent mailbox shows that the message was delivered with the expected recipient, subject, attachment filename, and attachment size.
Because the action is reported as failed after the non-idempotent side effect has completed, retrying the tool sends a duplicate email. In this occurrence, two calls both returned the same JSONDecodeError, and two separate messages appeared in Sent.
This is especially risky for autonomous agents because a normal retry policy can duplicate external writes while the tool result claims failure.
Recipient addresses and raw Gmail message/thread IDs are omitted for privacy.
What steps can reproduce the bug?
-
In the Windows Codex desktop app, connect the Gmail app/plugin.
-
Call the Gmail
send_emailaction with amultipart/mixedpayload containing:- a UTF-8
text/plainbody; - one
application/zipattachment supplied throughbody.base64_url_content; - attachment size: 2,160,477 bytes;
response_fields:snippetandsize_estimate.
- a UTF-8
-
Observe that the tool returns:
JSONDecodeError: Expecting value: line 1 column 1 (char 0) -
Search Gmail Sent for the exact recipient and subject.
-
Observe that the message exists in Sent and has the expected ZIP attachment and exact byte size.
-
Invoke the same action again after treating the first result as a failure.
-
Observe the same tool error and a second successfully sent email.
The issue reproduced on both consecutive calls during the same Codex task on 2026-08-14 (Asia/Seoul).
What is the expected behavior?
After Gmail accepts the message, send_email should return a successful tool result.
If response parsing fails after the send side effect, the connector should surface an indeterminate-delivery state rather than a definite failure, and ideally provide an idempotency/deduplication mechanism so retries cannot send duplicates.
Additional information
The MIME payload was valid enough for Gmail to preserve and send the attachment correctly. This does not appear to be an OAuth or permission failure because both messages are present under the SENT label with the expected attachment metadata.
The failure appears to occur after delivery, while the connector is decoding or normalizing the downstream response. The exact reason the downstream response was empty or non-JSON is not visible from the client-side tool result.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at the Gmail send_email entry point and trace the downstream response decoding after Gmail accepts the message. Reproduce with the multipart/mixed payload and inspect how an empty or non-JSON response is classified. Done means successful delivery is not reported as a definite failure, and retry behavior cannot silently create duplicate messages.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100