moeru-ai/airi · error · Error
Pinia synchronization is not installed. Call…
Error message
Pinia synchronization is not installed. Call app.use(synced.vue) first.
What it means
usePiniaSynced reads the SyncedPiniaRuntime via Vue inject using injectKeyPiniaSynced, which is only provided by the app's setupSynced plugin (installed via app.use(synced.vue)). If nothing provides the key, the composable throws rather than silently returning a no-op runtime, because cross-window Pinia synchronization cannot work without it.
Solutions
- Install the plugin during app bootstrap: app.use(pinia); app.use(synced.vue).
- In tests, build the app with the same plugin installation as production, or provide injectKeyPiniaSynced with a stub runtime.
- Ensure usePiniaSynced() is called inside a component setup/effect scope so inject works.
- Verify the secondary renderer's entry point runs the shared bootstrap that installs the plugin.
Example fix
// before const app = createApp(App) app.use(pinia) // after const app = createApp(App) app.use(pinia) app.use(synced.vue)
Defensive patterns
Strategy: type-guard
Type guard
function hasPiniaSynced(): boolean {
return inject(injectKeyPiniaSynced) !== undefined
} Try / catch
let runtime: SyncedPiniaRuntime
try {
runtime = usePiniaSynced()
} catch {
runtime = createNoopSyncedRuntime() // tests / non-synced windows
} Prevention
- Install synced.vue in a shared bootstrap used by every app entry and test harness.
- Call usePiniaSynced only inside component setup contexts.
- Add a smoke test that mounts the app and asserts the plugin provides the injection key.
When it happens
Trigger: Calling usePiniaSynced() in a component/store before (or without) the app installing the synced plugin — e.g. during early setup, in a test that mounts components without createApp().use(synced.vue), or in a secondary window whose bootstrap skipped plugin installation.
Common situations: Unit tests mounting components with a bare Pinia; a new Electron utility window that forgot setupSynced; calling the composable at module scope outside a component setup where inject cannot resolve.
Understand the failure class
Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.
Related errors
- [BackgroundStore] activeBackgroundUrl: No entry or URL…
- Cannot set motion: model not loaded
- Electron ipcRenderer is not available. Pass it explicitly…
- Failed to resolve chat provider
- No Live2D model source provided.
AI-assisted analysis of moeru-ai/airi@438a067dde (2026-09-17).
Data as JSON: /api/errors/620774a29a07f3ad.
Report an issue: GitHub.
Appendix: source
Thrown at packages/stage-ui/src/libs/pinia/synced-context.ts:13
import type { SyncedPiniaRuntime } from 'pinia-plugin-synced'
import type { InjectionKey } from 'vue'
import { inject } from 'vue'
/** Shares the installed runtime without importing its transport and election implementation. */
export const injectKeyPiniaSynced: InjectionKey<SyncedPiniaRuntime> = Symbol('stage-synced-pinia-runtime')
/** Returns the synchronization runtime installed by the application's setupSynced plugin. */
export function usePiniaSynced(): SyncedPiniaRuntime {
const runtime = inject(injectKeyPiniaSynced)
if (!runtime)
throw new Error('Pinia synchronization is not installed. Call app.use(synced.vue) first.')
return runtime
}
View on GitHub (pinned to 438a067dde)