Composables Issues
This page covers missing exports, bad imports, reactive pitfalls, and callback confusion in the generated client layer.
Composable is missing
Most often one of these is true:
- the matching generator is not enabled
- the composable name is based on a different
operationId - the app is importing from an old path
Current generated output lives under openapi/composables/ by default.
Examples:
openapi/composables/use-async-data/
openapi/composables/use-fetch/
openapi/composables/connectors/If a folder is missing, verify openapi.generators first.
export default defineNuxtConfig({
modules: ['nuxt-openapi-hyperfetch'],
openapi: {
input: './swagger.yaml',
generators: ['useFetch', 'useAsyncData'],
enableAutoImport: true,
},
})Import path is wrong
Use either auto-imported composables, or import from the generated openapi/ tree.
import { useAsyncDataGetPetById } from '~/openapi/composables/use-async-data'
import type { GetPetByIdData, Pet } from '~/openapi'If auto-import is enabled, you can call the composable directly without importing it manually.
Export name is different than expected
Composable names are derived from the OpenAPI operationId.
For example, an operation with operationId: getPetById generates names like:
useAsyncDataGetPetById
useAsyncDataGetPetByIdRaw
useFetchGetPetById
useFetchGetPetByIdRawIf you expected shorter resource-based names, inspect the actual generated index first.
useAsyncData composable does not accept the parameters you passed
Generated useAsyncData composables do not take a custom fetch handler. They wrap the request for you.
This is wrong for the current generator output:
useAsyncDataPets('pets', async () => {
return await $fetch('/api/pets')
})Use the generated signature instead:
const params = computed<GetPetByIdData>(() => ({
path: {
petId: Number(route.params.id),
},
}))
const { data, error } = useAsyncDataGetPetById(params)Many generated composables also support a custom cache key as the first argument.
const { data } = useAsyncDataGetPetById('pet-detail', {
path: { petId: 1 },
})Reactive params do not trigger a refresh
Pass a ref or computed, not a frozen snapshot.
const petId = ref(1)
const params = computed<GetPetByIdData>(() => ({
path: { petId: petId.value },
}))
const { data } = useAsyncDataGetPetById(params)
petId.value = 2If you pass a plain object created once, the request will not react to later state changes.
Auto-imports do not work
Auto-import depends on both module setup and generation output.
Check all of these:
enableAutoImportis notfalse- the relevant generator is enabled
- generation actually ran for the current command
- the app was restarted after a large output layout change
If needed, import from ~/openapi/composables/... directly to confirm the generated file exists.
Data is always undefined
When a generated composable returns no data, usually the request itself failed.
Inspect the error state before assuming the composable is broken.
const { data, error, status } = useAsyncDataGetPetById({
path: { petId: 1 },
})
console.log(status.value)
console.log(error.value)The most common root cause is a missing base URL:
export default defineNuxtConfig({
runtimeConfig: {
public: {
apiBaseUrl: process.env.NUXT_PUBLIC_API_BASE_URL || 'https://api.example.com',
},
},
})You can also pass baseURL per call.
Global headers are not applied
The runtime looks for global headers in one of these forms:
- a user composable named
useApiHeaders() - a Nuxt plugin that provides
$getApiHeaders
Example composable:
export const useApiHeaders = () => () => {
const token = useCookie('token')
return token.value
? { Authorization: `Bearer ${token.value}` }
: {}
}If your app uses another name, generated requests will not see it automatically.
Global callbacks are not firing
The runtime reads global callback rules from a Nuxt plugin that provides getGlobalApiCallbacks.
export default defineNuxtPlugin(() => {
const globalCallbacks = [
{
onError: (error: unknown) => {
console.error(error)
},
},
]
return {
provide: {
getGlobalApiCallbacks: () => globalCallbacks,
},
}
})If your plugin provides another property name, the runtime will ignore it.
Local callback never runs
Check both the local callback and the global callback chain.
- a failing request will skip local success handling
- a global callback may intentionally stop later execution
- the operation may be returning an error payload you are not logging yet
Start by logging error.value and keeping the local callback minimal.
SSR output does not match the browser
Hydration issues are usually rendering issues, not generator issues.
Render a stable loading state before using the data.
<script setup lang="ts">
const { data, pending } = useAsyncDataGetPetById({
path: { petId: 1 },
})
</script>
<template>
<div v-if="pending">Loading...</div>
<div v-else-if="data">{{ data.name }}</div>
</template>Checklist
When a generated composable looks broken, verify in this order:
- the required generator is enabled
- generation output exists under
openapi/composables/ - the export name matches the real
operationId - imports use the generated
openapi/tree or auto-import runtimeConfig.public.apiBaseUrlis set, orbaseURLis passed manually- global headers and callbacks use the exact names the runtime reads
