Error: You must `await server.start()` before calling `server.applyMiddleware()`
Asked Answered
G

4

8

After updating the apollo-server to version 3 the following error is shown in the console

C:\projects\my_project\node_modules\apollo-server-core\src\ApolloServer.ts:554
      throw new Error(
            ^
Error: You must `await server.start()` before calling `server.applyMiddleware()`
    at ApolloServer.assertStarted (C:\projects\my_project\node_modules\apollo-server-core\src\ApolloServer.ts:554:13)
    at ApolloServer.applyMiddleware (C:\projects\my_project\node_modules\apollo-server-express\src\ApolloServer.ts:60:10)
    at Object.<anonymous> (C:\projects\my_project\src\index.ts:17:14)
    at Module._compile (internal/modules/cjs/loader.js:1063:30)
    at Module.m._compile (C:\projects\my_project\node_modules\ts-node\src\index.ts:1225:23)
    at Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
    at Object.require.extensions.<computed> [as .ts] (C:\projects\my_project\node_modules\ts-node\src\index.ts:1228:12)
    at Module.load (internal/modules/cjs/loader.js:928:32)
    at Function.Module._load (internal/modules/cjs/loader.js:769:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)
[nodemon] app crashed - waiting for file changes before starting...

Adding server.start() before server.applyMiddleware() doesn't fix the problem. Any suggestions?

Gilmer answered 1/8, 2021 at 21:33 Comment(0)
G
8

I was able to fix the issue by following this guide in the documentation.

This example is copy-pasted from the documentation

import { ApolloServer } from 'apollo-server-express';
import express from 'express';

async function startApolloServer(typeDefs, resolvers) {
  // Same ApolloServer initialization as before
  const server = new ApolloServer({ typeDefs, resolvers });

  // Required logic for integrating with Express
  await server.start();

  const app = express();

  server.applyMiddleware({
     app,

     // By default, apollo-server hosts its GraphQL endpoint at the
     // server root. However, *other* Apollo Server packages host it at
     // /graphql. Optionally provide this to match apollo-server.
     path: '/'
  });

  // Modified server startup
  await new Promise(resolve => app.listen({ port: 4000 }, resolve));
  console.log(`πŸš€ Server ready at http://localhost:4000${server.graphqlPath}`);
}
Gilmer answered 1/8, 2021 at 21:48 Comment(1)
This fixed my issue. – Powdery
A
11

This is what worked for me as alternative to await server.start()

server.start().then(res => {
  server.applyMiddleware({ app, path: '/' });

  app.listen({ port }, () => 
    console.log(`Gateway API running at port: ${port}`)
  );  
});

This post led me to the answer.

Adlib answered 30/11, 2021 at 6:45 Comment(0)
F
9

In apollo server 3, you only include what you need. To integrate the required logic with Express, you need to call await server.start() after instantiating the server.

Example:

...

const apolloServer = new ApolloServer({
  schema,
  ... // other config
});

// without this, apollo will throw an error.
await apolloServer.start();

const app = express();

apolloServer.applyMiddleware({
  app,
  ... // other config
});

...

Check the new apollo docs for the changes here

Feu answered 18/8, 2021 at 8:59 Comment(0)
G
8

I was able to fix the issue by following this guide in the documentation.

This example is copy-pasted from the documentation

import { ApolloServer } from 'apollo-server-express';
import express from 'express';

async function startApolloServer(typeDefs, resolvers) {
  // Same ApolloServer initialization as before
  const server = new ApolloServer({ typeDefs, resolvers });

  // Required logic for integrating with Express
  await server.start();

  const app = express();

  server.applyMiddleware({
     app,

     // By default, apollo-server hosts its GraphQL endpoint at the
     // server root. However, *other* Apollo Server packages host it at
     // /graphql. Optionally provide this to match apollo-server.
     path: '/'
  });

  // Modified server startup
  await new Promise(resolve => app.listen({ port: 4000 }, resolve));
  console.log(`πŸš€ Server ready at http://localhost:4000${server.graphqlPath}`);
}
Gilmer answered 1/8, 2021 at 21:48 Comment(1)
This fixed my issue. – Powdery
P
4

If you are using Nextjs and want to implement an apollo server, this may help you:

pages/api/graphql.ts

import { ApolloServer } from "apollo-server-micro";
import { typeDefs } from "./schemas";
import { NextApiRequest, NextApiResponse } from "next";
import { ApolloServerPluginLandingPageGraphQLPlayground } from "apollo-server-core";
import { resolvers } from "./resolvers";

const GraphQLServer = new ApolloServer({
  introspection: true,
  typeDefs,
  resolvers,
  plugins: [ApolloServerPluginLandingPageGraphQLPlayground()],
});
const startServer = GraphQLServer.start();

export default async function handler(
  req: NextApiRequest,
  res: NextApiResponse
) {
  res.setHeader("Access-Control-Allow-Credentials", "true");
  res.setHeader(
    "Access-Control-Allow-Origin",
    "https://studio.apollographql.com"
  );
  res.setHeader(
    "Access-Control-Allow-Headers",
    "Origin, X-Requested-With, Content-Type, Accept, Access-Control-Allow-Methods, Access-Control-Allow-Origin, Access-Control-Allow-Credentials, Access-Control-Allow-Headers"
  );
  res.setHeader(
    "Access-Control-Allow-Methods",
    "POST, GET, PUT, PATCH, DELETE, OPTIONS, HEAD"
  );
  if (req.method === "OPTIONS") {
    res.end();
    return false;
  }

  await startServer;
  await GraphQLServer.createHandler({
    path: "/api/graphql",
  })(req, res);
}

export const config = {
  api: {
    bodyParser: false,
  },
};

/pages/api/resolvers.js

import axios from "axios";

export const resolvers = {
  Query: {
    getUsers: async () => {
      console.log("users");
      try {
        const users = await axios.get("https://api.github.com/users");
        return users.data.map(({ id, login, avatar_url }) => ({
          id,
          login,
          avatar_url,
        }));
      } catch (error) {
        throw error;
      }
    },
    getUser: async (_, args) => {
      try {
        const user = await axios.get(
          `https://api.github.com/users/${args.name}`
        );
        return {
          id: user.data.id,
          login: user.data.login,
          avatar_url: user.data.avatar_url,
        };
      } catch (error) {
        throw error;
      }
    },
  },
};

/pages/api/schemas.ts

import { gql } from "apollo-server-micro";

export const typeDefs = gql`
  type User {
    id: ID
    login: String
    avatar_url: String
  }

  type Query {
    getUsers: [User]
    getUser(name: String!): User!
  }
`;

Petersburg answered 22/9, 2022 at 0:41 Comment(2)
Mate, you saved my day. Thanks a lot. apolloServer.start() did not work in request handler. So moving it out helped me. Also, allowing studio url in cors helped me too. – Arlo
Appreciate this! – Valve

© 2022 - 2024 β€” McMap. All rights reserved.