Fix: useAsyncData Must Return a Value (Not Undefined)

Error message:
[nuxt] `useAsyncData` must return a value (it should not be `undefined`)
data fetching 2025-01-25

What Causes This Error?

This error occurs when your useAsyncData or useFetch handler function returns undefined instead of actual data. Nuxt expects a value to be returned so it can properly handle the data on both server and client.

Common Causes and Fixes

Cause 1: Missing Return Statement

// ❌ Wrong - no return statement
const { data } = await useAsyncData('key', () => {
  $fetch('/api/users')  // Missing return!
})

// ✅ Correct - return the fetch result
const { data } = await useAsyncData('key', () => {
  return $fetch('/api/users')
})

// ✅ Or use implicit return with arrow function
const { data } = await useAsyncData('key', () => $fetch('/api/users'))

Cause 2: Conditional Returns

// ❌ Wrong - might return undefined
const { data } = await useAsyncData('key', () => {
  if (someCondition) {
    return $fetch('/api/users')
  }
  // Returns undefined if condition is false!
})

// ✅ Correct - always return something
const { data } = await useAsyncData('key', () => {
  if (someCondition) {
    return $fetch('/api/users')
  }
  return []  // Return empty array or default value
})

Cause 3: Async Function Without Return

// ❌ Wrong - async function doesn't return
const { data } = await useAsyncData('key', async () => {
  const response = await $fetch('/api/users')
  console.log(response)
  // Forgot to return!
})

// ✅ Correct
const { data } = await useAsyncData('key', async () => {
  const response = await $fetch('/api/users')
  console.log(response)
  return response
})

Cause 4: Error Swallowing

// ❌ Wrong - catching error but not returning
const { data } = await useAsyncData('key', async () => {
  try {
    return await $fetch('/api/users')
  } catch (error) {
    console.error(error)
    // Returns undefined on error!
  }
})

// ✅ Correct - return a default value on error
const { data } = await useAsyncData('key', async () => {
  try {
    return await $fetch('/api/users')
  } catch (error) {
    console.error(error)
    return []  // Return default value
  }
})

Cause 5: Using forEach Instead of Map

// ❌ Wrong - forEach doesn't return
const { data } = await useAsyncData('key', async () => {
  const ids = [1, 2, 3]
  const results = []
  ids.forEach(async (id) => {
    results.push(await $fetch(`/api/users/${id}`))
  })
  return results  // This will be empty!
})

// ✅ Correct - use Promise.all with map
const { data } = await useAsyncData('key', async () => {
  const ids = [1, 2, 3]
  const results = await Promise.all(
    ids.map(id => $fetch(`/api/users/${id}`))
  )
  return results
})

The useFetch Shorthand

If you’re just fetching data without transformation, useFetch handles the return automatically:

// This automatically returns the fetch result
const { data } = await useFetch('/api/users')

Handling Null vs Undefined

Note that null is a valid return value, but undefined is not:

// ✅ OK - null is acceptable
const { data } = await useAsyncData('key', () => {
  return null
})

// ❌ Error - undefined is not acceptable
const { data } = await useAsyncData('key', () => {
  return undefined
})

Debugging Tips

Add console logs to trace the return value:

const { data } = await useAsyncData('key', async () => {
  const result = await $fetch('/api/users')
  console.log('Returning:', result, 'Type:', typeof result)
  return result
})

TypeScript Helps

Using TypeScript can catch this error at compile time:

// TypeScript will warn if return type could be undefined
const { data } = await useAsyncData<User[]>('key', async (): Promise<User[]> => {
  // TypeScript enforces you return User[]
  return await $fetch('/api/users')
})

Quick Reference

PatternValid?
() => $fetch('/api')✅ Yes
() => { $fetch('/api') }❌ No (missing return)
() => { return $fetch('/api') }✅ Yes
async () => { await $fetch('/api') }❌ No (missing return)
() => someCondition ? data : undefined❌ No
() => someCondition ? data : null✅ Yes
() => someCondition ? data : []✅ Yes