You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Sumo Logic中出现ERR_HTTP_HEADERS_SENT错误,请求排查原因

[ERR_HTTP_HEADERS_SENT] 错误根源定位与修复

错误核心本质

ERR_HTTP_HEADERS_SENT 是因为HTTP响应已经发送给客户端后,代码仍尝试修改响应头(比如设置Cookie)或再次发送响应。结合你提供的三段代码,问题根源在于回调函数被重复调用,导致后续操作多次触发响应头修改。

具体代码问题分析

1. 重试逻辑导致重复回调

这段代码是触发重复回调的关键:

awsService.sendEvent(req, payload, function(err, resp) {
    if (err) {
      if (tries <= 3) {
        tries++;
        return sendEvent(req, payload, tries, cb);
      }
    }

    return cb();
  });

问题点:当err存在且tries <=3时,代码递归调用sendEvent,但当前回调函数的后续代码return cb()依然会执行。也就是说,无论重试是否触发,cb()都会被调用一次,加上重试后sendEvent内部的回调,最终导致cb被多次调用。

2. 最外层回调重复执行响应操作

最外层回调包含res.cookie操作,一旦cb被多次调用,这段代码就会重复执行:

sendEvent(req, payload, 1, function (err, response) {
    if (err) {
      req.mtShout.error('[ANALYTICS ERROR]', err);
    }
    if (!_.get(req, ['currentClient','oneTrust', 'enabled']) ||
      (
        _.get(req, ['optanonConsent', 'groups']) &&
        req.optanonConsent.groups.indexOf(req.currentClient.oneTrust.categories.performance + ':1') > -1
      )
    ) {
      res.cookie(COOKIE_NAME, payload.session_id, {
        maxAge: config.server.raCookieMaxAge,
        secure: secureCookieFlag,
        httpOnly: true
      });
    }
    req.raSession = payload.session_id;
  });

问题点:如果res.cookie被执行两次,而第一次执行时响应已经通过res.send/res.json等方式发送给客户端,第二次执行res.cookie就会触发ERR_HTTP_HEADERS_SENT错误。

3. 底层sendEvent函数的潜在隐患

let sendEvent = function (req, payload, cb) {
  if (process.env.NODE_LOCAL === 'true' && !process.env.DEBUG) {
    req.mtShout.debug('No QUEUE Submission because this is local ENV');
    return cb(null, true);
  }

  sqs.getQueueUrl({QueueName: awsConfig.queueName}, function(e, d){
    if (e) {
      req.mtShout.error("Error when putting RA message onto SQS: ", e);

      e = new Error("Failed to put RA event onto SQS queue");
      cb(e, null); // 缺少return,若后续代码变更可能导致cb被多次调用
    } else {
      sqs.sendMessage({
        MessageBody: JSON.stringify(payload),
        QueueUrl: d.QueueUrl
      }, function(err, data) {
        if(err) {
          req.mtShout.error("Error when putting RA message onto SQS: ", err);

          err = new Error("Failed to put RA event onto SQS queue");
          cb(err, null); // 同样缺少return
        } else {
          req.mtShout.debug('Successfully queued ' + payload.event_name + ' RA event', data);
          cb(null, true);
        }
      });
    }
  });
};

问题点:错误分支调用cb后没有加return,当前逻辑下不会触发问题,但后续代码迭代时可能引发cb多次调用的风险。

修复方案

修复重试逻辑的重复回调

调整重试逻辑,确保cb只被调用一次:

awsService.sendEvent(req, payload, function(err, resp) {
    if (err) {
      if (tries <= 3) {
        tries++;
        sendEvent(req, payload, tries, cb);
        return; // 终止当前函数,避免执行后续的cb()
      }
    }
    cb(err); // 统一在最后调用cb,错误时传入err,无错时传入undefined
  });

补充底层sendEvent的return语句

在错误分支调用cb后添加return,保证逻辑严谨性:

// 修复sqs.getQueueUrl错误分支
if (e) {
  req.mtShout.error("Error when putting RA message onto SQS: ", e);
  e = new Error("Failed to put RA event onto SQS queue");
  return cb(e, null);
}

// 修复sqs.sendMessage错误分支
if(err) {
  req.mtShout.error("Error when putting RA message onto SQS: ", err);
  err = new Error("Failed to put RA event onto SQS queue");
  return cb(err, null);
}

验证响应发送时机

确保执行res.cookie的代码在响应发送(res.send/res.json等)之前完成,避免在响应已发送后修改响应头。

内容的提问来源于stack exchange,提问作者HMech

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 18:36:25