N
Nuxt5d ago
Toffe

Trying to use a Pinia store in a global middleware for auth check fails

It fails with an error:
Uncaught Error: [🍍]: "getActivePinia()" was called but there was no active Pinia. Are you trying to use a store before calling "app.use(pinia)"?
Uncaught Error: [🍍]: "getActivePinia()" was called but there was no active Pinia. Are you trying to use a store before calling "app.use(pinia)"?
So using a store in a global middleware is not possible? Or am i missing something? Code is like this in "auth.global.ts"
import { useUserStore } from "~/store/user"

const userStore = useUserStore();

export default defineNuxtRouteMiddleware((to, from) => {
if (!userStore.isLoggedIn) {
return navigateTo('/login')
}
})
import { useUserStore } from "~/store/user"

const userStore = useUserStore();

export default defineNuxtRouteMiddleware((to, from) => {
if (!userStore.isLoggedIn) {
return navigateTo('/login')
}
})
5 Replies
kapa.ai
kapa.ai5d ago
Hi @Toffe. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- The issue you're encountering is a common one when trying to use Pinia stores in global middleware. The problem occurs because the middleware runs before Pinia is fully initialized in the Nuxt application lifecycle. Solution There are a few approaches to solve this: 1. Use useNuxtApp() to access Pinia in the correct context Instead of initializing the store outside the middleware function, move it inside:
export default defineNuxtRouteMiddleware((to, from) => {
const userStore = useUserStore();

if (!userStore.isLoggedIn) {
return navigateTo('/login')
}
})
export default defineNuxtRouteMiddleware((to, from) => {
const userStore = useUserStore();

if (!userStore.isLoggedIn) {
return navigateTo('/login')
}
})
2. Use useState instead of Pinia for authentication state Nuxt's built-in useState composable is designed to work in all contexts including middleware:
export default defineNuxtRouteMiddleware((to, from) => {
const isAuthenticated = useState('authenticated')

if (!isAuthenticated.value) {
return navigateTo('/login')
}
})
export default defineNuxtRouteMiddleware((to, from) => {
const isAuthenticated = useState('authenticated')

if (!isAuthenticated.value) {
return navigateTo('/login')
}
})
Then you can update this state when users log in/out as shown in the Nuxt docs. 3. For complex cases, use runWithContext If you have a more complex setup and absolutely need to use your Pinia store in middleware, you can try:
export default defineNuxtRouteMiddleware((to, from) => {
const nuxtApp = useNuxtApp();
const userStore = nuxtApp.runWithContext(() => useUserStore());

if (!userStore.isLoggedIn) {
return navigateTo('/login')
}
})
export default defineNuxtRouteMiddleware((to, from) => {
const nuxtApp = useNuxtApp();
const userStore = nuxtApp.runWithContext(() => useUserStore());

if (!userStore.isLoggedIn) {
return navigateTo('/login')
}
})
This approach was mentioned as a solution in a GitHub issue with a similar problem in this GitHub issue. Why this happens The error occurs because middleware runs very early in the Nuxt lifecycle, sometimes before Pinia is fully initialized. This is particularly true for global middleware (with the .global suffix), which runs on every route change. Remember that Nuxt 3 has moved away from Vuex (used in Nuxt 2) to Pinia as the recommended state management solution, so some patterns need to be adjusted accordingly. Hope this helps solve your authentication middleware issue! ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5d ago
<@260145305754927104> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
Toffe
ToffeOP5d ago
how would usestate be implemented into my store? @kapa.ai
kapa.ai
kapa.ai5d ago
Let me check the knowledge base for you again. One moment! :books: ---------------------- Based on your previous question about using Pinia in a global middleware, I understand you're now asking how to implement useState with your existing store setup. Here's how you can do it: Implementing useState with your Pinia store You have two main approaches: 1. Use useState alongside your Pinia store You can create a shared authentication state using useState that works in all contexts (including middleware):
// composables/auth.ts
export const useAuth = () => useState('authenticated', () => false)

// In your Pinia store, sync with this state
import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
state: () => ({
// other user data
}),
getters: {
isLoggedIn() {
const auth = useAuth()
return auth.value
}
},
actions: {
login() {
const auth = useAuth()
auth.value = true
// other login logic
},
logout() {
const auth = useAuth()
auth.value = false
// other logout logic
}
}
})
// composables/auth.ts
export const useAuth = () => useState('authenticated', () => false)

// In your Pinia store, sync with this state
import { defineStore } from 'pinia'

export const useUserStore = defineStore('user', {
state: () => ({
// other user data
}),
getters: {
isLoggedIn() {
const auth = useAuth()
return auth.value
}
},
actions: {
login() {
const auth = useAuth()
auth.value = true
// other login logic
},
logout() {
const auth = useAuth()
auth.value = false
// other logout logic
}
}
})
Then in your middleware:
export default defineNuxtRouteMiddleware((to, from) => {
const isAuthenticated = useAuth()

if (!isAuthenticated.value) {
return navigateTo('/login')
}
})
export default defineNuxtRouteMiddleware((to, from) => {
const isAuthenticated = useAuth()

if (!isAuthenticated.value) {
return navigateTo('/login')
}
})
2. Replace Pinia with useState for simpler state management If your authentication logic is simple, you might consider using useState directly:
// composables/user.ts
export const useUserStore = () => {
const user = useState('user', () => ({
isLoggedIn: false,
// other user data
}))

function login(userData) {
user.value = {
...userData,
isLoggedIn: true
}
}

function logout() {
user.value.isLoggedIn = false
}
return {
user,
login,
logout,
// computed property to get isLoggedIn directly
isLoggedIn: computed(() => user.value.isLoggedIn)
}
}
// composables/user.ts
export const useUserStore = () => {
const user = useState('user', () => ({
isLoggedIn: false,
// other user data
}))

function login(userData) {
user.value = {
...userData,
isLoggedIn: true
}
}

function logout() {
user.value.isLoggedIn = false
}
return {
user,
login,
logout,
// computed property to get isLoggedIn directly
isLoggedIn: computed(() => user.value.isLoggedIn)
}
}
Then in your middleware:
import { useUserStore } from '~/composables/user'

export default defineNuxtRouteMiddleware((to, from) => {
const { isLoggedIn } = useUserStore()

if (!isLoggedIn.value) {
return navigateTo('/login')
}
})
import { useUserStore } from '~/composables/user'

export default defineNuxtRouteMiddleware((to, from) => {
const { isLoggedIn } = useUserStore()

if (!isLoggedIn.value) {
return navigateTo('/login')
}
})
The advantage of useState is that it's specifically designed for Nuxt's SSR environment and works in all contexts including middleware as shown in the Nuxt docs. Remember that useState serializes your state to JSON, so it can't contain classes, functions, or symbols - only plain data that can be serialized. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai5d ago
<@260145305754927104> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?