Skip to content

v3: $fetch intercepted by internal routing during SSR - external API calls fail #3953

@productdevbook

Description

@productdevbook

Environment

  • Nitro version: latest (via nuxt@33005)
  • Node.js: v24.11.0
  • OS: macOS

Describe the bug

When using $fetch to make external HTTP requests during SSR (in a Nuxt plugin), the requests are intercepted by Nitro's internal routing instead of making actual HTTP calls. This causes:

  1. Vue Router warnings: No match found for location with path "/api/graphql"
  2. 404 errors even though the external API is accessible via curl

Reproduction

In a server plugin (app/plugins/store.server.ts):

// This gets intercepted by Nitro instead of making an actual HTTP request
const response = await $fetch('http://localhost:4001/api/store/mystore')

Server logs show:

[Store Plugin] Fetching from Go API: http://localhost:4001/api/store/deneme
[Store Middleware] host: undefined  // <-- middleware triggered with undefined host
[Vue Router warn]: No match found for location with path "/api/store/deneme"
[Store Plugin] Go API error: [GET] "http://localhost:4001/api/store/deneme": 404 OK

But curl http://localhost:4001/api/store/test works perfectly and returns valid JSON.

Expected behavior

$fetch with an absolute URL (including different port) should make an actual HTTP request, not go through Nitro's internal routing.

Workaround

Using node:http directly bypasses the interception:

import http from 'node:http'

function goFetch<T>(path: string): Promise<{ data: T | null }> {
  return new Promise((resolve) => {
    const req = http.request({
      hostname: 'localhost',
      port: 4001,
      path,
      method: 'GET',
    }, (res) => {
      let body = ''
      res.on('data', chunk => body += chunk)
      res.on('end', () => {
        if (res.statusCode !== 200) {
          resolve({ data: null })
          return
        }
        resolve({ data: JSON.parse(body) as T })
      })
    })
    req.on('error', () => resolve({ data: null }))
    req.end()
  })
}

Additional context

  • This happens in development mode
  • The same issue occurs with ofetch imported directly from the package
  • Even native fetch gets intercepted (Nitro polyfills it)
  • The middleware runs multiple times with host: undefined for each intercepted request

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions