Fix: Nitro Is Not Initialized Yet in Nuxt

Error message:
Nitro is not initialized yet. You cannot access `nitro` before Nuxt is ready.
initialization 2025-01-25

What Causes This Error?

This error occurs when you try to access Nuxt’s Nitro server instance before it has been initialized. Nitro handles server-side rendering and API routes, but it’s not available immediately.

The Problem

// modules/my-module.ts
export default defineNuxtModule({
  setup(options, nuxt) {
    // ❌ Wrong - Nitro not ready yet
    console.log(nuxt.options.nitro)  // Might work
    nuxt.server  // Error! Server not initialized
  }
})

The Fix

Wait for Nitro to Initialize

// modules/my-module.ts
export default defineNuxtModule({
  setup(options, nuxt) {
    // ✅ Use hooks to wait for Nitro
    nuxt.hook('nitro:init', (nitro) => {
      // Nitro is now available
      console.log('Nitro initialized:', nitro.options.preset)
    })

    nuxt.hook('nitro:config', (nitroConfig) => {
      // Modify Nitro config before initialization
      nitroConfig.preset = 'node-server'
    })
  }
})

Nitro Lifecycle Hooks

export default defineNuxtModule({
  setup(options, nuxt) {
    // Before Nitro config is resolved
    nuxt.hook('nitro:config', (nitroConfig) => {
      // Modify config
      nitroConfig.routeRules = {
        '/api/**': { cors: true }
      }
    })

    // After Nitro is initialized
    nuxt.hook('nitro:init', (nitro) => {
      // Access Nitro instance
      console.log('Preset:', nitro.options.preset)
      console.log('Output dir:', nitro.options.output.dir)
    })

    // Before Nitro build
    nuxt.hook('nitro:build:before', (nitro) => {
      console.log('Building Nitro...')
    })

    // After Nitro build
    nuxt.hook('nitro:build:public-assets', (nitro) => {
      console.log('Public assets ready')
    })
  }
})

Common Use Cases

Modify Server Routes

export default defineNuxtModule({
  setup(options, nuxt) {
    nuxt.hook('nitro:config', (nitroConfig) => {
      // Add route rules
      nitroConfig.routeRules = {
        ...nitroConfig.routeRules,
        '/api/**': {
          cors: true,
          headers: {
            'Access-Control-Allow-Origin': '*'
          }
        }
      }
    })
  }
})

Add Server Plugins

import { createResolver } from '@nuxt/kit'

export default defineNuxtModule({
  setup(options, nuxt) {
    const resolver = createResolver(import.meta.url)

    nuxt.hook('nitro:config', (nitroConfig) => {
      nitroConfig.plugins = nitroConfig.plugins || []
      nitroConfig.plugins.push(resolver.resolve('./runtime/server/plugin'))
    })
  }
})

Configure Presets

export default defineNuxtModule({
  setup(options, nuxt) {
    nuxt.hook('nitro:config', (nitroConfig) => {
      // Set deployment preset
      if (process.env.VERCEL) {
        nitroConfig.preset = 'vercel'
      } else if (process.env.NETLIFY) {
        nitroConfig.preset = 'netlify'
      }
    })
  }
})

Add Virtual Server Files

export default defineNuxtModule({
  setup(options, nuxt) {
    nuxt.hook('nitro:config', (nitroConfig) => {
      nitroConfig.virtual = {
        ...nitroConfig.virtual,
        '#my-module/config': `export default ${JSON.stringify(options)}`
      }
    })
  }
})

Accessing Nitro Options

In nuxt.config.ts

// nuxt.config.ts
export default defineNuxtConfig({
  nitro: {
    // Direct Nitro configuration
    preset: 'node-server',
    compressPublicAssets: true,

    routeRules: {
      '/api/**': { cors: true }
    },

    storage: {
      redis: {
        driver: 'redis',
        url: process.env.REDIS_URL
      }
    }
  }
})

Reading Nitro Config

export default defineNuxtModule({
  setup(options, nuxt) {
    nuxt.hook('nitro:init', (nitro) => {
      // Read final config
      console.log('Storage:', nitro.options.storage)
      console.log('Route rules:', nitro.options.routeRules)
      console.log('Output:', nitro.options.output)
    })
  }
})

Dev Server Access

export default defineNuxtModule({
  setup(options, nuxt) {
    // Access dev server (development only)
    nuxt.hook('listen', (server, { url }) => {
      console.log(`Server running at ${url}`)
    })

    // Vite dev server
    nuxt.hook('vite:serverCreated', (viteServer) => {
      console.log('Vite server created')
    })
  }
})

Error Handling

export default defineNuxtModule({
  setup(options, nuxt) {
    nuxt.hook('nitro:init', (nitro) => {
      try {
        // Safe to access Nitro
        doSomethingWithNitro(nitro)
      } catch (error) {
        console.error('Nitro error:', error)
      }
    })
  }
})

Quick Checklist

  • Don’t access Nitro directly in module setup
  • Use nitro:config hook to modify configuration
  • Use nitro:init hook to access Nitro instance
  • Use nuxt.config.ts nitro option for static config
  • Handle both dev and production scenarios
  • Check for dev-only features (like Vite server)