content: Multiple calls with find() later gives error: nuxt instance unavailable

Environment


  • Operating System: Linux
  • Node Version: v16.14.2
  • Nuxt Version: 3.0.0-rc.6-27638947.92269dd
  • Package Manager: yarn@1.22.10
  • Builder: vite
  • User Config: modules
  • Runtime Modules: @nuxt/content@2.1.0-27639343.b832f24, @nuxt/ui@0.2.0-27638810.adb0eb6
  • Build Modules: -

Reproduction

https://stackblitz.com/edit/github-4fmlha?file=app.vue

Describe the bug

when there are multiple calls to the queryContent() and later both calls to find(). The first instance works and the second instance gives error: nuxt instance unavailable.

It is a very straightforward usage, written in the reproduction link in the app.vue file.

Additional context

<script setup>
const { data: posts } = await useAsyncData('equal', async () => {
  const posts1 = queryContent('/posts/');
  const posts2 = queryContent('/posts/');

 // first call succeed
  try {
    await posts1.find();
  } catch (e) {
    console.log("error from 1st call")
    console.log(e)
  }

  // second call gives error
  try {
    const posts =  await posts2.find();
    return posts
  } catch(e) {
    console.log("error from 2nd call")
    console.log(e)
  }
});
</script>

Simple usage of query content fails.

Logs

Error: nuxt instance unavailable
    at useNuxtApp (file:///home/projects/github-4fmlha/.nuxt/dist/server/server.mjs:488:13)
    at Module.useRuntimeConfig (file:///home/projects/github-4fmlha/.nuxt/dist/server/server.mjs:496:10)
    at Module.withContentBase (file:///home/projects/github-4fmlha/.nuxt/dist/server/server.mjs:10843:102)
    at eval (file:///home/projects/github-4fmlha/.nuxt/dist/server/server.mjs:10624:41)
    at Object.find (file:///home/projects/github-4fmlha/.nuxt/dist/server/server.mjs:10687:17)
    at eval (file:///home/projects/github-4fmlha/.nuxt/dist/server/server.mjs:16449:33)
    at async setup (file:///home/projects/github-4fmlha/.nuxt/dist/server/server.mjs:16456:12

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 15 (12 by maintainers)

Most upvoted comments

Anyway, FWIW I talked this through with @manniL and created this repro, with various examples of working and non-working double-calls to Content:

@farnabaz - not sure if this is helpful, as you already commented on Nuxt’s “internal magic”, but should I file a new issue with this repro?

EDIT: Having read through this article which @manniL posted, checked the StackBlitz repo which @farnabaz posted, and reviewed the comments about useNuxtApp() my guess is that queryContent() is interacting with the Nuxt instance, so the first await nukes the ability of the second awaited function to work with the Nuxt context, and so the function fails. I wonder if this could be caught and reported?

This is a known behavior of Nuxt, If you wish to use multiple fetch/find inside asyncData, you need to await for all of them at once.

const { data: posts } = await useAsyncData('equal', async () => {
  const posts1 = queryContent('/posts/');
  const posts2 = queryContent('/posts/');
  const [res1, res2] = await Promise.all([
    posts1.find()
    posts2.find()
  ])
});

Well regarding “this is the way it is”: I think that there should be documentation about this. That is what we could provide.

As of why this is the case, I can’t really provide more information. Just one sidenote: Our case here is different from your example. There is a callback function inside the await. The code is:

const { data: content1 } = await useAsyncData('content1', () => queryContent('/content1').findOne())

But not according to your example:

const { data: content1 } = await useAsyncData('content1')

Maybe that’s the reason for this issue?

It’s all very well saying “it’s by design” but for a framework whose slogan is “the intuitive framework” this is about as far away from intuitive as you can get. I think nuxt is quite intuitive in general compared to others. But this is kind of off-topic here.

At the very least, Nuxt should ship with a linter rule which tells you you can’t do this, because of some internal gymnastics. Feel free to contribute that!

Hey @luksak,

Perhaps I should be more explicit.

In vanilla JS, the following hypothetical code would most likely work fine:

// normal async js: works
const data = await getAsyncData(async () => {
  const foo = await getFoo()
  const bar = await getBar()
  return { foo, bar }
})

But in Nuxt, for some reason, the almost exact same setup only works works with a Promise.all():

// nuxt: needs Promise.all()
const data = await useAsyncData('some-key', async () => {
  const [foo, bar] = await Promise.all([
    getFoo(),
    getBar(),
  ])
  return { foo, bar }
}

So my question is, why is this so?

It’s all very well saying “it’s by design” but for a framework whose slogan is “the intuitive framework” this is about as far away from intuitive as you can get.

At the very least, Nuxt should ship with a linter rule which tells you you can’t do this, because of some internal gymnastics.

So, do we know why this is so? Or is it just <waves hands magically> “the way it is” ?

Hey there,

Just been tripped up by this and said some very hurtful things to my computer in the process!

@farnabaz, you mention:

This is a known behavior of Nuxt, If you wish to use multiple fetch/find inside asyncData, you need to await for all of them at once.

I am somewhat of a fairweather Nuxter; that is, I really don’t think I “know” Nuxt; it always trips me up, for example, things like this.

How is this a “known behaviour”? Can I find this in the Nuxt or Content docs somewhere? Is there a “big list of things you should know about Nuxt before you throw your computer out the window” anywhere?

There is always something with Nuxt. It’s frustrating. Help appreciated!