Node.js 18读取S3 JSON文件时触发TypeError: Converting circular structure to JSON错误
Node.js 18 使用 @aws-sdk/client-s3 读取S3 JSON文件时出现循环引用序列化错误
错误详情
TypeError: Converting circular structure to JSON --> starting at object with constructor 'TLSSocket' | property 'parser' -> object with constructor 'HTTPParser' --- property 'socket' closes the circle at JSON.stringify (<anonymous>) at responseHook (/opt/wrapper.js:147:24) at /opt/nodejs/node_modules/@opentelemetry/instrumentation-aws-sdk/build/src/aws-sdk.js:149:61 at safeExecuteInTheMiddle (/opt/nodejs/node_modules/@opentelemetry/instrumentation/build/src/utils.js:28:18) at AwsInstrumentation._callUserResponseHook (/opt/nodejs/node_modules/@opentelemetry/instrumentation-aws-sdk/build/src/aws-sdk.js:149:54) at /opt/nodejs/node_modules/@opentelemetry/instrumentation-aws-sdk/build/src/aws-sdk.js:269:34 at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
场景与代码片段
在Node.js 18环境下,使用@aws-sdk/client-s3的S3Client和GetObjectCommand读取S3中的JSON文件,调用.transformToString('utf-8')将返回内容转为字符串时触发了上述错误,相关代码如下:
const client = new S3Client({ region }); const params = { Bucket: bucket, Key: key }; const response = await client.send(new GetObjectCommand(params)); const body = await response.Body.transformToString('utf-8');
解决方案
这个错误和transformToString本身无关,是OpenTelemetry的AWS SDK instrumentation插件在序列化响应对象时,试图处理包含循环引用的TLSSocket等底层网络对象导致的。可通过以下方式解决:
禁用OpenTelemetry对AWS SDK的自动 instrumentation
如果不需要追踪AWS SDK调用,可直接在代码中关闭该插件,或在部署配置中移除相关依赖。示例代码:const { NodeTracerProvider } = require('@opentelemetry/sdk-trace-node'); const { registerInstrumentations } = require('@opentelemetry/instrumentation'); const { AwsInstrumentation } = require('@opentelemetry/instrumentation-aws-sdk'); registerInstrumentations({ instrumentations: [ // 移除或注释掉AWS SDK instrumentation的初始化代码 // new AwsInstrumentation(), ], });修改responseHook逻辑,避免序列化整个响应对象
如果必须保留追踪,需调整/opt/wrapper.js第147行的responseHook实现,只序列化业务所需字段(比如响应体内容),不要直接序列化包含底层网络连接的完整response对象。临时替换响应体读取方式
可以绕开transformToString,改用流读取方式临时规避错误:const { Readable } = require('stream'); const response = await client.send(new GetObjectCommand(params)); const body = await new Promise((resolve, reject) => { const chunks = []; Readable.from(response.Body) .on('data', chunk => chunks.push(chunk)) .on('end', () => resolve(Buffer.concat(chunks).toString('utf-8'))) .on('error', reject); });
内容的提问来源于stack exchange,提问作者shakya-abhi
相关产品推荐
相关产品推荐

