Search code examples
javascriptnode.jsjwtbackendfastify

'AVV_ERR_PLUGIN_NOT_VALID' error in fastify


i was trying to set up the environmental variables in my fastify - react app. why am I getting the 'AVV_ERR_PLUGIN_NOT_VALID' error for the following fastify code? thank you! :

const fastify = require('fastify')({ 
    logger: {
      level: 'debug',
    }
  });
  
  console.log('hello from server.js 1 !');
  
  // setting up cors:
  const cors = require("@fastify/cors");  
  fastify.register(cors, { origin: "*" });
  
  // setting up environment variables
  const fastifyEnv = require('@fastify/env');
  const envSchema = {
    type: 'object',
    required: ['YOUTUBE_DATA_API_KEY', 'TESTVAR', 'GOOGLE_CLIENT_ID', 'GOOGLE_CLIENT_SECRET', 'JWT_SECRET'],
    properties: {
      YOUTUBE_DATA_API_KEY: { type: 'string' },
      TESTVAR: { type: 'string' },
      GOOGLE_CLIENT_ID: { type: 'string' },
      GOOGLE_CLIENT_SECRET: { type: 'string' },
      JWT_SECRET: { type: 'string' }     
    } 
  };
  const options = {
    confKey: 'config', 
    schema: envSchema,
    dotenv: {
      path: `${__dirname}/.env`,
      debug: true
    }
  };
  
  fastify.register(fastifyEnv, options);
  
  fastify.ready(err => {
    if (err) throw err;
    console.log('fastify.config at server.js: ', fastify.config);
  
    const fastifyJwt = require('@fastify/jwt');
    fastify.register(fastifyJwt, { secret: fastify.config.JWT_SECRET });
  });
  
  // setting up authentication:
  fastify.decorate('verifyJWTandLevel', (request, reply, done) => {
    done();
  }).decorate('verifyUserAndPassword', (request, reply, done) => {
    done();
  }).register(require('@fastify/auth')).after(() => {
    fastify.route({
      method: 'POST',
      url: '/auth-multiple',
      preHandler: fastify.auth([fastify.verifyJWTandLevel, fastify.verifyUserAndPassword]),
      handler: (req, reply) => {
        req.log.info('Auth route');
        reply.send({ hello: 'world' });
      }
    });
  });
  
  // other setup...
  
  const videoRouter = require('./src/routes/videoRouter');
  fastify.register(videoRouter, { prefix: '/api/v1' });
  
  fastify.get('/', (request, reply) => {
    console.log('hello from server.js 5000!');
    reply.send({ hello: 'fastify server at 5000!' });
  });
  
  // Start function
  const start = async () => {
    try {
      await fastify.listen({
        port: 5000,
        address: '0.0.0.0'
      });
      console.log('Server is running on port 5000');
    } catch (err) {
      fastify.log.error(err);
      process.exit(1);
    }
  };
 
  fastify.ready(err => {
    if (err) throw err;
    start();
  });
  

complete error stack:

[FASTIFY] AvvioError [Error]: Root plugin has already booted [FASTIFY] at Boot._addPlugin (/home/totoro/vc_app/vc-app/node_modules/avvio/boot.js:244:11) [FASTIFY] at Boot.use (/home/totoro/vc_app/vc-app/node_modules/avvio/boot.js:216:25) [FASTIFY] at server. [as register] (/home/totoro/vc_app/vc-app/node_modules/avvio/boot.js:40:14) [FASTIFY] at /home/totoro/vc_app/vc-app/backend/server.js:42:13 [FASTIFY] at manageErr (/home/totoro/vc_app/vc-app/node_modules/fastify/fastify.js:595:11) [FASTIFY] at exit (/home/totoro/vc_app/vc-app/node_modules/fastify/lib/hooks.js:110:5) [FASTIFY] at manageTimeout (/home/totoro/vc_app/vc-app/node_modules/fastify/lib/hooks.js:127:11) [FASTIFY] at _encapsulateThreeParam (/home/totoro/vc_app/vc-app/node_modules/avvio/boot.js:562:7) [FASTIFY] at Boot.timeoutCall (/home/totoro/vc_app/vc-app/node_modules/avvio/boot.js:458:5) [FASTIFY] at Boot.callWithCbOrNextTick (/home/totoro/vc_app/vc-app/node_modules/avvio/boot.js:440:19) { [FASTIFY] code: 'AVV_ERR_PLUGIN_NOT_VALID'


Solution

  • When you call the ready method, the fastify server starts the boot.

    After the boot you can't add decorators, hooks or plugins.

    So, your issue can be replicated with the code:

    const app = require('fastify')({ logger: true })
    
    app.ready((err) => {
      app.register(function plugin (app, opts, next) {
        next()
      })
    })
    

    To solve it you need to remove the ready call.

    Note that if you must await a plugin, you can await the register() method.