Skip to content

Commit 3b5f60c

Browse files
committed
fix: patch gaxios v7 Array.toString() stream corruption
gaxios v7.1.3 reads stream error bodies using Array.toString() which joins Buffer chunks with commas, corrupting JSON error responses at TCP chunk boundaries. This was introduced when google-auth-library was upgraded from v9 to v10 in #18880, pulling in gaxios v7. This adds a postinstall script that patches all gaxios v7 copies, replacing response.toString() with response.join('') to concatenate chunks without stray commas.
1 parent ea6617a commit 3b5f60c

2 files changed

Lines changed: 96 additions & 1 deletion

File tree

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@
5555
"telemetry": "node scripts/telemetry.js",
5656
"check:lockfile": "node scripts/check-lockfile.js",
5757
"clean": "node scripts/clean.js",
58-
"pre-commit": "node scripts/pre-commit.js"
58+
"pre-commit": "node scripts/pre-commit.js",
59+
"postinstall": "node scripts/patch_gaxios.js"
5960
},
6061
"overrides": {
6162
"wrap-ansi": "9.0.2",

scripts/patch_gaxios.js

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/**
2+
* @license
3+
* Copyright 2026 Google LLC
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/**
8+
* Postinstall patch for gaxios v7.x to fix the Array.toString() bug.
9+
*
10+
* In gaxios v7.x, the _request method reads stream error bodies like:
11+
* const response = [];
12+
* for await (const chunk of data) { response.push(chunk); }
13+
* translatedResponse.data = response.toString();
14+
*
15+
* Array.toString() joins elements with commas, corrupting the response body
16+
* at TCP chunk boundaries. This patch replaces `response.toString()` with
17+
* `response.join('')` which concatenates without commas.
18+
*
19+
* See: https://github.com/googleapis/gaxios/issues/XXX
20+
*/
21+
22+
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
23+
import { join, dirname } from 'node:path';
24+
import { fileURLToPath } from 'node:url';
25+
26+
const __dirname = dirname(fileURLToPath(import.meta.url));
27+
const rootDir = join(__dirname, '..');
28+
29+
function patchFile(filePath) {
30+
if (!existsSync(filePath)) return false;
31+
32+
const content = readFileSync(filePath, 'utf8');
33+
const bugPattern = 'translatedResponse.data = response.toString()';
34+
35+
if (!content.includes(bugPattern)) return false;
36+
37+
const patched = content.replace(
38+
bugPattern,
39+
"translatedResponse.data = response.join('')",
40+
);
41+
writeFileSync(filePath, patched, 'utf8');
42+
return true;
43+
}
44+
45+
// Find and patch all gaxios v7 copies
46+
const gaxiosPaths = [
47+
// packages/core workspace copy
48+
join(rootDir, 'packages/core/node_modules/gaxios/build/cjs/src/gaxios.js'),
49+
join(rootDir, 'packages/core/node_modules/gaxios/build/esm/src/gaxios.js'),
50+
// @google/genai nested copy (root)
51+
join(
52+
rootDir,
53+
'node_modules/@google/genai/node_modules/gaxios/build/cjs/src/gaxios.js',
54+
),
55+
join(
56+
rootDir,
57+
'node_modules/@google/genai/node_modules/gaxios/build/esm/src/gaxios.js',
58+
),
59+
// @google/genai nested copy (packages/core workspace)
60+
join(
61+
rootDir,
62+
'packages/core/node_modules/@google/genai/node_modules/gaxios/build/cjs/src/gaxios.js',
63+
),
64+
join(
65+
rootDir,
66+
'packages/core/node_modules/@google/genai/node_modules/gaxios/build/esm/src/gaxios.js',
67+
),
68+
// Top-level (if ever hoisted)
69+
join(rootDir, 'node_modules/gaxios/build/cjs/src/gaxios.js'),
70+
join(rootDir, 'node_modules/gaxios/build/esm/src/gaxios.js'),
71+
// Old gaxios layout (single build dir)
72+
join(rootDir, 'packages/core/node_modules/gaxios/build/src/gaxios.js'),
73+
join(
74+
rootDir,
75+
'node_modules/@google/genai/node_modules/gaxios/build/src/gaxios.js',
76+
),
77+
join(rootDir, 'node_modules/gaxios/build/src/gaxios.js'),
78+
];
79+
80+
let patchedCount = 0;
81+
for (const p of gaxiosPaths) {
82+
if (patchFile(p)) {
83+
patchedCount++;
84+
console.log(` ✓ Patched: ${p.replace(rootDir + '/', '')}`);
85+
}
86+
}
87+
88+
if (patchedCount > 0) {
89+
console.log(
90+
`\n gaxios postinstall: patched ${patchedCount} file(s) — fixed Array.toString() stream corruption bug`,
91+
);
92+
} else {
93+
console.log(' gaxios postinstall: no files needed patching');
94+
}

0 commit comments

Comments
 (0)