5

I'm working on a Hapi server for a ReactJS app but when I try to deploy to Heroku, I get the R10 error "Failed to bind to $PORT within 60 seconds of launch". What is going on? I'm using process.env.PORT. I also tried parseInt() around it. Also tried disabling varying packages. The build is successful always.

In the Heroku logs, I see the console log from the index.js ("Hapi running on ...") but then the R10 error shows up and the server restarts, then crashes.

==> 🌎 Hapi Production Server (API) is listening on http://localhost:14316 2016-01-22T15:10:33.947571+00:00 heroku[web.1]: Stopping process with SIGKILL 2016-01-22T15:10:33.947571+00:00 heroku[web.1]: Error R10 (Boot timeout) -> Web process failed to bind to $PORT within 60 seconds of launch 2016-01-22T15:10:34.737554+00:00 heroku[web.1]: State changed from starting to crashed 2016-01-22T15:10:34.724233+00:00 heroku[web.1]: Process exited with status 137

This all runs fine locally when I run with NODE_ENV=production

src/server.js

import Hapi from 'hapi';
import Inert from 'inert';
import jwt from 'hapi-auth-jwt2';
import React from 'react';
import { renderToString } from 'react-dom/server';
import { RoutingContext, match } from 'react-router';
import { Provider } from 'react-redux';
import createRoutes from './routes';
import configureStore from './store/configureStore';
import Html from './Html';

const PROTOCOL = 'http://';
const SERVER_HOST = process.env.HOST || 'localhost';
const SERVER_PORT = process.env.PORT || 3000;
const API_HOST = process.env.API_HOST || 'localhost';
const API_PORT = process.env.API_PORT || 8000;

export default function(callback) {

    const server = new Hapi.Server();

    server.connection({
    host: SERVER_HOST,
    port: SERVER_PORT,
    labels: ['api'],
    // routes: {
    //   cors: {
    //     origin: [PROTOCOL + API_HOST + ':' + API_PORT]
    //   }
    // }
  });

    server.connections[0].name = 'API';

    server.register([
        { register: Inert },
        { register: jwt },
        // {
      //   register: api,
      //   routes: {
      //     prefix: '/api'
      //   }
      // }
    ], (err) => {
    if(err) {
      console.error('ERROR:', err)
      throw err;
    }

        server.route({
        method: 'GET',
        path: '/{param*}',
        handler: {
          directory: {
            path: 'static'
          }
        }
      });

        server.ext('onPreResponse', (request, reply) => {

            if (typeof request.response.statusCode !== 'undefined') {
        return reply.continue();
      }

            const assets = {
                javascript: {
                    main: '/dist/bundle.js'
                }
            };

          const store = configureStore();
          const routes = createRoutes(store);

          // this gets called if server side rendering/routing has problems and errors
          function hydrateOnClient() {
            reply('<!doctype html>\n' +
              renderToString(<Html assets={assets} store={store} />)).code(500);
          }

          match({ routes, location: request.path }, (error, redirectLocation, renderProps) => {

            if (redirectLocation) {

              res.redirect(301, redirectLocation.pathname + redirectLocation.search)

            } else if (error) {
              console.error('ROUTER ERROR:', error) // eslint-disable-line no-console
              hydrateOnClient();

            } else if (!renderProps) {

              // in some cases this would act as a 404 but that should be handled in the routes
              hydrateOnClient();

            } else {

              const component = (
                <Provider store={store}>
                  <RoutingContext {...renderProps} />
                </Provider>
              );

              reply('<!doctype html>\n' +
                renderToString(<Html assets={assets} component={component} store={store} />)
                    );
            }
          });
        });
    });

    return server.start((err) => {

        if(err) {
            console.log(err);
            throw err;
        }

        callback(server)
    });

}

index.js

require('babel-core/register');

global.__DEVELOPMENT__ = process.env.NODE_ENV !== 'production';
global.__SERVER__ = true;
global.__CLIENT__ = false;

const server = require('./src/server');

server(server => {
   for (var key of Object.keys(server.connections)) {
     console.info('==> 🌎 Hapi Production Server (' + server.connections[key].name + ') is listening on', server.connections[key].info.uri);
  }
});

1 Answer 1

11

process.env.HOST was undefined on Heroku, and for some reason it didn't like localhost as the host, which caused the issue.

I simply removed the host var all together, so connection looks like:

server.connection({
  port: process.env.PORT || 3000,
  labels: ['api'],
})
Sign up to request clarification or add additional context in comments.

4 Comments

thank you! this was starting to drive me nuts because I had the process.env.PORT set up just fine. it was indeed that Heroku didn't like server.connection({ port: PORT, host: 'localhost' }); removing the host param entirely, as you suggested, worked. as such: server.connection({ port: PORT }); cheers!
I had the same problem and I also resolved it by not defining the host property
~2 hrs wasted today trying to fix this. Thanks!
I'm curious to know how did you find this? It was even breaking my MySQL connection.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.