
Vue Pinia Best Practices
Stop Vue 3 apps from crashing on the common Pinia “no active Pinia” error by fixing plugin order and where you call useXxxStore().
Overview
vue-pinia-best-practices is an agent skill for the Build phase that fixes Vue 3 Pinia “no active Pinia” crashes by enforcing correct plugin order and store call timing.
Install
npx skills add https://github.com/hyf0/vue-skills --skill vue-pinia-best-practicesWhat is this skill?
- Explains the getActivePinia() crash and when it fires relative to app.mount().
- 5-item task checklist: plugin order, router guards, no module-level store calls, setup-only usage, script setup vs class
- Documents wrong vs correct app.use(pinia) before router when guards touch stores.
- Flags top-level useXxxStore() and early <script> execution as root causes.
- Tagged as a high-impact gotcha for Vue 3 Pinia initialization.
- 5-item task checklist for Pinia setup timing
- Documented impact level: HIGH for startup crashes
Adoption & trust: 2.3k installs on skills.sh; 2.5k GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your Vue app boots or navigates and throws getActivePinia() because stores are used before Pinia is installed or outside setup-safe contexts.
Who is it for?
Indie devs adding Pinia to a fresh Vue 3 SPA or debugging first-route crashes when guards read auth state.
Skip if: Teams on Nuxt with built-in Pinia wiring already correct, or backends that do not touch Vue entry/bootstrap.
When should I use this skill?
Vue 3 app crashes or logs getActivePinia() during boot, first navigation, or after adding a new store used in router guards.
What do I get? / Deliverables
After applying the checklist, Pinia is active before mount and router guards, and store calls only run in setup or composables so the app starts without the pineapple error.
- Corrected main bootstrap order (pinia before router/mount)
- Store usage confined to setup/composables per checklist
Recommended Skills
Journey fit
Pinia install timing and store access patterns are fixed while wiring the Vue frontend, before or right after first integration of state into routing and components. The skill is entirely about Vue 3 + Pinia client state setup in main.ts/main.js and SFC script boundaries—not backend or shipping tooling.
How it compares
Use this targeted gotcha guide instead of generic Vue docs when you already know the error string and need bootstrap order spelled out.
Common Questions / FAQ
Who is vue-pinia-best-practices for?
Solo and indie builders shipping Vue 3 frontends with Pinia who hit initialization timing errors during router or store setup.
When should I use vue-pinia-best-practices?
During Build / frontend when adding Pinia to main.ts, ordering plugins before vue-router, or removing module-level useStore() calls in new features.
Is vue-pinia-best-practices safe to install?
It is documentation-style guidance with no runtime hooks; review the Security Audits panel on this Prism page before trusting any third-party skill package.
SKILL.md
READMESKILL.md - Vue Pinia Best Practices
# Fix "No Active Pinia" Error - Store Setup Timing **Impact: HIGH** - The error "getActivePinia() was called but there was no active Pinia" is one of the most common Pinia errors. It occurs when you try to use a store before Pinia has been installed on the Vue app, causing your application to crash. ## Task Checklist - [ ] Ensure `app.use(pinia)` is called before `app.mount()` - [ ] Ensure `app.use(pinia)` is called before `app.use(router)` if router guards use stores - [ ] Never call `useXxxStore()` in module-level (top-level) code - [ ] Only call `useXxxStore()` inside setup functions, composables, or after app initialization - [ ] Check for `<script setup>` vs `<script>` - the latter runs too early ## The Error ``` [🍍]: "getActivePinia()" was called but there was no active Pinia. Did you forget to install pinia? ``` ## Common Cause 1: Wrong Plugin Order ```javascript // main.js - WRONG ORDER import { createApp } from 'vue' import { createPinia } from 'pinia' import router from './router' // Router uses a store in navigation guard import App from './App.vue' const app = createApp(App) // WRONG: Router is installed first, but its guards use stores app.use(router) // Router guard calls useAuthStore() - FAILS! app.use(createPinia()) app.mount('#app') ``` **Fix: Install Pinia first:** ```javascript // main.js - CORRECT ORDER import { createApp } from 'vue' import { createPinia } from 'pinia' import router from './router' import App from './App.vue' const app = createApp(App) // CORRECT: Pinia installed before anything that uses stores app.use(createPinia()) app.use(router) // Now router guards can safely use stores app.mount('#app') ``` ## Common Cause 2: Store Used at Module Level ```javascript // api.js - WRONG: Module-level store usage import { useAuthStore } from '@/stores/auth' // This runs immediately when the module is imported! const authStore = useAuthStore() // ERROR: No active Pinia yet export function fetchUser() { return fetch('/api/user', { headers: { Authorization: `Bearer ${authStore.token}` } }) } ``` **Fix: Call useStore inside functions:** ```javascript // api.js - CORRECT: Store used inside function import { useAuthStore } from '@/stores/auth' export function fetchUser() { // Store is accessed when function is called, not when module loads const authStore = useAuthStore() return fetch('/api/user', { headers: { Authorization: `Bearer ${authStore.token}` } }) } ``` ## Common Cause 3: Script Tag Missing "setup" ```vue <!-- WRONG: <script> runs before component setup --> <script> import { useUserStore } from '@/stores/user' // This runs too early, before the component is set up const userStore = useUserStore() // ERROR! export default { // ... } </script> ``` **Fix: Use `<script setup>` or move to setup function:** ```vue <!-- CORRECT: <script setup> runs at the right time --> <script setup> import { useUserStore } from '@/stores/user' // This runs during component setup, Pinia is active const userStore = useUserStore() // Works! </script> ``` ```vue <!-- CORRECT: Options API with setup function --> <script> import { useUserStore } from '@/stores/user' export default { setup() { // Called during component initialization const userStore = useUserStore() // Works! return { userStore } } } </script> ``` ## Common Cause 4: mapStores with Parentheses ```vue <script> import { mapStores } from 'pinia' import { useProductsStore } from '@/stores/products' export default { computed: { // WRONG: Called the function instead of passing it ...mapStores(useProductsStore()) // ERROR! } } </script> ``` **Fix: Pass the function referen