LoginSignup
2
1

More than 5 years have passed since last update.

Express + Firebase Admin SDKでCan't set headers after they are sentと言われてサーバーが落ちる対処

Posted at

Express(Admin)でFirebase Realitime Databaseを更新する
イベント発火したらこんな感じのコード

const ref = firebase.database.ref('/hoge');
ref.update({
  state: 1,
});

1度目の更新でコンソールエラー発生

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at validateHeader (_http_outgoing.js:503:11)
    at ServerResponse.setHeader (_http_outgoing.js:510:3)
    at ServerResponse.header (/Users/naototakahashi/Projects/Lite/UHLiteBackOffice/node_modules/express/lib/response.js:730:10)
    at ServerResponse.contentType (/Users/naototakahashi/Projects/Lite/UHLiteBackOffice/node_modules/express/lib/response.js:558:15)
    at ServerResponse.send (/Users/naototakahashi/Projects/Lite/UHLiteBackOffice/node_modules/express/lib/response.js:145:14)
    at done (/Users/naototakahashi/Projects/Lite/UHLiteBackOffice/node_modules/express/lib/response.js:967:10)
    at Object.exports.renderFile (/Users/naototakahashi/Projects/Lite/UHLiteBackOffice/node_modules/jade/lib/index.js:374:12)
    at View.exports.__express [as engine] (/Users/naototakahashi/Projects/Lite/UHLiteBackOffice/node_modules/jade/lib/index.js:417:11)
    at View.render (/Users/naototakahashi/Projects/Lite/UHLiteBackOffice/node_modules/express/lib/view.js:127:8)
    at tryRender (/Users/naototakahashi/Projects/Lite/UHLiteBackOffice/node_modules/express/lib/application.js:640:10)

コンソールがエラーを吐く
パラメータを変えて再度更新

FIREBASE WARNING: Exception was thrown by user callback. TypeError: req.next is not a function
    at done (/Users/naototakahashi/Projects/Lite/UHLiteBackOffice/node_modules/express/lib/response.js:966:25)
    at tryRender (/Users/naototakahashi/Projects/Lite/UHLiteBackOffice/node_modules/express/lib/application.js:642:5)
    at Function.render (/Users/naototakahashi/Projects/Lite/UHLiteBackOffice/node_modules/express/lib/application.js:592:3)
    at ServerResponse.render (/Users/naototakahashi/Projects/Lite/UHLiteBackOffice/node_modules/express/lib/response.js:971:7)
    at /Users/naototakahashi/Projects/Lite/UHLiteBackOffice/routes/index.js:27:9
    at /Users/naototakahashi/Projects/Lite/UHLiteBackOffice/node_modules/@firebase/database/dist/cjs/src/core/view/EventRegistration.js:65:22
    at Object.exports.exceptionGuard (/Users/naototakahashi/Projects/Lite/UHLiteBackOffice/node_modules/@firebase/database/dist/cjs/src/core/util/util.js:556:9)
    at EventList.raise (/Users/naototakahashi/Projects/Lite/UHLiteBackOffice/node_modules/@firebase/database/dist/cjs/src/core/view/EventQueue.js:158:24)
    at EventQueue.raiseQueuedEventsMatchingPredicate_ (/Users/naototakahashi/Projects/Lite/UHLiteBackOffice/node_modules/@firebase/database/dist/cjs/src/core/view/EventQueue.js:111:41)
    at EventQueue.raiseEventsForChangedPath (/Users/naototakahashi/Projects/Lite/UHLiteBackOffice/node_modules/@firebase/database/dist/cjs/src/core/view/EventQueue.js:95:14) 
/Users/naototakahashi/Projects/Lite/UHLiteBackOffice/node_modules/@firebase/database/dist/cjs/src/core/util/util.js:567
            throw e;

TypeError: req.next is not a function
    at done (/Users/naototakahashi/Projects/Lite/UHLiteBackOffice/node_modules/express/lib/response.js:966:25)
    at tryRender (/Users/naototakahashi/Projects/Lite/UHLiteBackOffice/node_modules/express/lib/application.js:642:5)
    at Function.render (/Users/naototakahashi/Projects/Lite/UHLiteBackOffice/node_modules/express/lib/application.js:592:3)
    at ServerResponse.render (/Users/naototakahashi/Projects/Lite/UHLiteBackOffice/node_modules/express/lib/response.js:971:7)
    at /Users/naototakahashi/Projects/Lite/UHLiteBackOffice/routes/index.js:27:9
    at /Users/naototakahashi/Projects/Lite/UHLiteBackOffice/node_modules/@firebase/database/dist/cjs/src/core/view/EventRegistration.js:65:22
    at Object.exports.exceptionGuard (/Users/naototakahashi/Projects/Lite/UHLiteBackOffice/node_modules/@firebase/database/dist/cjs/src/core/util/util.js:556:9)
    at EventList.raise (/Users/naototakahashi/Projects/Lite/UHLiteBackOffice/node_modules/@firebase/database/dist/cjs/src/core/view/EventQueue.js:158:24)
    at EventQueue.raiseQueuedEventsMatchingPredicate_ (/Users/naototakahashi/Projects/Lite/UHLiteBackOffice/node_modules/@firebase/database/dist/cjs/src/core/view/EventQueue.js:111:41)
    at EventQueue.raiseEventsForChangedPath (/Users/naototakahashi/Projects/Lite/UHLiteBackOffice/node_modules/@firebase/database/dist/cjs/src/core/view/EventQueue.js:95:14)
Waiting for the debugger to disconnect...

サーバー自体落ちました。
このエラー系はresを2回返すと発生するらしいが、そんな記憶もなく。

対処

on('value')をonce('value')に変更する。

on('value')が悪さをしているという記事はあったが、ref.update()は一度しか発火しないだろと思ってたところ、

/**
* Routings
*/

/* GET Dashboard page */
router.get('/', function(req, res) {
  const ref = db.ref('/');
  ref.on('value', function(snapshot){
    res.render('index', { 
      data: snapshot.val()
    });
  });
});

/**
 * Login
 */

router.get('/login', function(req, res) {
  res.render('login');
});

イベントが発火するルーティングとは異なる"/"(ルート)にてonが使われていました。onceにしてエラー発生せず。

onでリッスン状態になっているのが原因?
別ルーティングだと思って気にしてなかったので、かなりハマりました。

Ref

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1