Skip to content

fix(cli): reject fetchJson on malformed JSON or response stream errors - #28875

Open
chelsealong wants to merge 2 commits into
google-gemini:mainfrom
chelsealong:fix/github-fetch-malformed-json-28646
Open

fix(cli): reject fetchJson on malformed JSON or response stream errors#28875
chelsealong wants to merge 2 commits into
google-gemini:mainfrom
chelsealong:fix/github-fetch-malformed-json-28646

Conversation

@chelsealong

Copy link
Copy Markdown

Summary

fetchJson() in packages/cli/src/config/extensions/github_fetch.ts collects
response chunks and calls JSON.parse(data) inside the response's end event
callback with no try/catch, and the response stream has no error listener.
A malformed or truncated JSON body returned with HTTP 200 throws a
SyntaxError from that callback instead of rejecting the returned promise,
so extension commands can crash instead of receiving an actionable error.

Fix

  • Wrap JSON.parse in try/catch and reject with a contextual error
    including the URL and status code.
  • Add a response stream error listener that rejects with a contextual
    error instead of leaving the promise pending or throwing unhandled.

This is a minimal, targeted fix scoped to the exact defect described in the
issue; it does not change redirect handling, header handling, or any other
behavior of fetchJson().

Related Issues

Fixes #28646

Tests

Added two regression tests to github_fetch.test.ts:

  • malformed JSON returned with HTTP 200 now rejects with a contextual
    "Failed to parse JSON from ..." error instead of throwing.
  • a response stream error event now rejects with a contextual
    "Response stream error while fetching ..." error.

Verified both new tests fail against the pre-fix code
(git checkout HEAD~1 -- packages/cli/src/config/extensions/github_fetch.ts)
with:

FAIL  packages/cli/src/config/extensions/github_fetch.test.ts > fetchJson > should reject on malformed JSON instead of throwing
AssertionError: expected [Function] to throw error matching /Failed to parse JSON from .../ but got
'Expected property name or '}' in JSON at position 1 (line 1 column 2)'

FAIL  packages/cli/src/config/extensions/github_fetch.test.ts > fetchJson > should reject on response stream error
AssertionError: expected [Function] to throw error matching /Response stream error while fetching/ but got
'socket hang up'

And passing after restoring the fix:

 Test Files  1 passed (1)
      Tests  10 passed (10)

How to Validate

npx vitest run packages/cli/src/config/extensions/github_fetch.test.ts
npx eslint packages/cli/src/config/extensions/github_fetch.ts packages/cli/src/config/extensions/github_fetch.test.ts
npx prettier --check packages/cli/src/config/extensions/github_fetch.ts packages/cli/src/config/extensions/github_fetch.test.ts
npm run typecheck --workspace @google/gemini-cli

All pass:

  • github_fetch.test.ts: 10/10 tests passing
  • packages/cli/src/config/extensions/: 181/181 tests passing (no regressions)
  • eslint: clean
  • prettier: clean
  • typecheck: clean

Pre-Merge Checklist

  • Added/updated tests
  • Noted breaking changes — none; previously-uncaught exceptions now
    surface as promise rejections with more context, matching the
    existing behavior for other fetchJson() failure modes.

AI assistance disclosure

This change was prepared with the assistance of an AI coding agent
(Claude, Anthropic) operating under human supervision.

Malformed or truncated GitHub API responses returned with HTTP 200
threw an uncaught SyntaxError from inside the response 'end' callback
instead of rejecting the fetchJson() promise, and the response stream
had no 'error' listener. Wrap JSON.parse in try/catch and listen for
stream errors so both cases reject with contextual errors that the
caller's existing error handling can report.

Fixes google-gemini#28646
@chelsealong
chelsealong requested a review from a team as a code owner August 18, 2026 02:37
@github-actions github-actions Bot added the size/m A medium sized PR label Aug 18, 2026
@github-actions

Copy link
Copy Markdown

📊 PR Size: size/M

  • Lines changed: 52
  • Additions: +50
  • Deletions: -2
  • Files changed: 2

@gemini-cli gemini-cli Bot added priority/p2 Important but can be addressed in a future release. area/extensions Issues related to Gemini CLI extensions capability labels Aug 18, 2026
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request improves the robustness of the fetchJson utility by addressing unhandled exceptions during JSON parsing and response stream processing. By adding explicit error handling, the function now gracefully rejects promises with actionable context when encountering malformed data or network stream failures, preventing potential CLI crashes.

Highlights

  • Error Handling Improvement: Wrapped JSON parsing in a try/catch block to prevent crashes when receiving malformed JSON, ensuring the promise rejects with a descriptive error instead.
  • Stream Reliability: Added an error listener to the response stream to properly handle and propagate stream-level errors, preventing unhandled exceptions.
  • Regression Testing: Introduced two new test cases to verify that malformed JSON and stream errors are correctly caught and rejected with appropriate context.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request improves error handling in the fetchJson function by catching response stream errors and handling malformed JSON parsing gracefully, with corresponding unit tests added. The feedback suggests handling the potentially undefined statusCode property on the IncomingMessage object by using a nullish coalescing operator to provide a fallback value in the error messages.

Comment on lines +50 to +56
res.on('error', (err) => {
reject(
new Error(
`Response stream error while fetching ${url} (status ${res.statusCode}): ${err.message}`,
),
);
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

The statusCode property on IncomingMessage is optional and can be undefined. According to the repository's general rules, when consuming an object where a property is optional in its type definition, callers must handle the undefined case (e.g., by providing a default with ??). Please use a nullish coalescing operator to provide a fallback value.

        res.on('error', (err) => {
          reject(
            new Error(
              'Response stream error while fetching ' +
                url +
                ' (status ' +
                (res.statusCode ?? 'unknown') +
                '\nnetwork error: ' +
                err.message,
            ),
          );
        });
References
  1. When consuming an object, if a property is optional in its type definition (interface), callers must handle the undefined case (e.g., by providing a default with ??).

Comment on lines +63 to +69
reject(
new Error(
`Failed to parse JSON from ${url} (status ${res.statusCode}): ${
err instanceof Error ? err.message : String(err)
}`,
),
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

The statusCode property on IncomingMessage is optional and can be undefined. According to the repository's general rules, when consuming an object where a property is optional in its type definition, callers must handle the undefined case (e.g., by providing a default with ??). Please use a nullish coalescing operator to provide a fallback value.

            reject(
              new Error(
                'Failed to parse JSON from ' +
                  url +
                  ' (status ' +
                  (res.statusCode ?? 'unknown') +
                  '\nnetwork error: ' +
                  (err instanceof Error ? err.message : String(err)),
              ),
            );
References
  1. When consuming an object, if a property is optional in its type definition (interface), callers must handle the undefined case (e.g., by providing a default with ??).

@chelsealong

Copy link
Copy Markdown
Author

Addressed both inline comments: added ?? 'unknown' fallback for res.statusCode in the two new error messages, since statusCode is optional on IncomingMessage. All 10 tests, eslint, prettier, and typecheck pass.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/extensions Issues related to Gemini CLI extensions capability priority/p2 Important but can be addressed in a future release. size/m A medium sized PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: malformed GitHub API JSON can crash extension operations

1 participant