{"record":{"id":"654772ab8819d82c","repo":"balderdashy/sails","slug":"cannot-write-to-response-more-than-once","errorCode":null,"errorMessage":"Cannot write to response more than once","messagePattern":"Cannot write to response more than once","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/router/res.js","lineNumber":423,"sourceCode":"\n\n\n  return res;\n\n\n};\n\n\n/**\n * NOTE: ALL RESPONSES (INCLUDING REDIRECTS) ARE PREVENTED ONCE THE RESPONSE HAS BEEN SENT!!\n * Even though this is not strictly required with sockets, since res.redirect()\n * is an HTTP-oriented method from Express, it's important to maintain consistency.\n *\n * @api private\n */\nfunction onlyAllowOneResponse (res) {\n  if (res._virtualResponseStarted) {\n    throw new Error('Cannot write to response more than once');\n  }\n  res._virtualResponseStarted = true;\n}\n\n\n// The constructor for clientRes stream\n// (just a normal transform stream)\nfunction MockClientResponse() {\n  Transform.call(this);\n}\nutil.inherits(MockClientResponse, Transform);\nMockClientResponse.prototype._transform = function(chunk, encoding, next) {\n  this.push(chunk);\n  next();\n};\n","sourceCodeStart":405,"sourceCodeEnd":439,"githubUrl":"https://github.com/balderdashy/sails/blob/7b76422cc27823df033572bdda5c4910a68b697f/lib/router/res.js#L405-L439","documentation":"Sails virtual responses (res.view, res.json, res.send, etc.) guard against writing to the underlying HTTP response twice. `onlyAllowOneResponse` throws this error if a second response method is invoked after a previous one already started writing, because the Node/Express response stream can only be ended once.","triggerScenarios":"Calling two response methods in one request handler, e.g. `res.json(...)` followed by `res.view(...)` or `res.redirect(...)` after a body was already sent; missing `return` after the first response call in an async branch; calling res.* again after res.ok/res.serverError.","commonSituations":"Forgetting `return res.json(...)` so the next line also responds; responding both in a promise .then and .catch; double-responding when a policy/handler already sent a response.","solutions":["Add `return` before the first response call (e.g. `return res.json(...)`) so execution stops after responding.","Audit the handler/policies chain for code paths that can both respond.","If responding in async callbacks, check `res.headersSent`/flow so only one path responds.","Move fallback responses into .catch blocks that are skipped on success."],"exampleFix":"// before\nres.json({ ok: true });\nres.view('pages/home');\n// after\nreturn res.json({ ok: true });","handlingStrategy":"try-catch","validationCode":"if (res.headersSent || res._virtualResponseStarted) { return; } // before issuing another response","typeGuard":"function canRespond(res) { return !res.headersSent && !res._virtualResponseStarted; }","tryCatchPattern":"try { return res.json(data); } catch (e) { if (e.message === 'Cannot write to response more than once') { sails.log.warn('double response in handler'); return; } throw e; }","preventionTips":["Always `return` response calls (return res.json(...)).","Ensure only one of policy/handler/controller paths sends the response.","In promise chains, respond in either then or catch, never both.","Grep handlers for consecutive res.* calls during code review."],"tags":["sails","response","double-response","http"],"backgroundTag":"headers-already-sent","analyzedSha":"7b76422cc27823df033572bdda5c4910a68b697f","analyzedAt":"2026-09-01T04:01:57.104Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}