moeru-ai/airi · warning
[BackgroundStore] activeBackgroundUrl: No entry or URL found
Error message
[BackgroundStore] activeBackgroundUrl: No entry or URL found for ID "${lookupId}" What it means
Warn from the background store's activeBackgroundUrl computed. The active card references a background through extensions.airi.modules.activeBackgroundId (normalized from the 'image-journal-' prefix to the storage prefix), but entries has no record with that ID, so the computed returns null and the scene renders without its background. The entry-existence gate also exists so backgrounds deleted in other windows stop rendering via stale cached blob URLs.
Source
Thrown at packages/stage-ui/src/stores/background.ts:232
// Normalize prefix just in case they stored 'image-journal-xyz'
let lookupId = bgId
if (bgId.startsWith('image-journal-')) {
lookupId = bgId.replace('image-journal-', STORAGE_PREFIX)
}
// Return the reactive URL from our map if it exists and the entry is still valid
const entryExists = entries.value.has(lookupId)
const url = backgroundUrls[lookupId] ?? null
// NOTICE: We gate the return on entry existence to ensure deleted backgrounds
// (removed from other windows) do not keep rendering via a stale cached URL.
if (url && entryExists) {
return url
}
const entry = entries.value.get(lookupId)
if (!entry) {
console.warn(`[BackgroundStore] activeBackgroundUrl: No entry or URL found for ID "${lookupId}"`)
return null
}
return null // Should have been caught by backgroundUrls check above if entry is valid
})
const getCharacterBackgrounds = computed(() => (characterId?: string) => {
const list = Array.from(entries.value.values()).filter((e) => {
// Shared (builtin/scene) or Journal/Selfie for specific character
return e.type === 'scene' || e.type === 'builtin' || ((e.type === 'journal' || e.type === 'selfie') && characterId && e.characterId === characterId)
})
return list.map(e => ({
...e,
url: backgroundUrls[e.id] ?? null,
})).sort((a, b) => b.createdAt - a.createdAt)
})
// List of available backgrounds for the current characterView on GitHub (pinned to 677329427f)
Solutions
- If this fires once at startup, ignore it - hydration finishes asynchronously and the computed re-evaluates
- If persistent, reset the stale reference: set extensions.airi.modules.activeBackgroundId to 'none' or to an ID present in getCharacterBackgrounds
- Re-create the missing background (re-upload or re-journal the image) so entries.value.has(lookupId) becomes true
- Check the BroadcastChannel 'airi:background-sync' flow when multiple windows are open - deletion in another window is intentionally honored here
Example fix
// before
const bgUrl = backgroundStore.activeBackgroundUrl.value
// after: tolerate the hydration window and the deleted case
const bgUrl = computed(() =>
backgroundStore.loading.value ? null : backgroundStore.activeBackgroundUrl.value,
)
watch(bgUrl, (url) => {
if (!url) resetToDefaultScene()
}) Defensive patterns
Strategy: type-guard
Validate before calling
if (!backgroundStore.loading.value) {
const url = backgroundStore.activeBackgroundUrl.value
if (!url) resetToDefaultScene()
} Type guard
function hasBackgroundEntry(
entries: ReadonlyMap<string, unknown>,
id: string | undefined | null,
): id is string {
return typeof id === 'string' && id !== 'none' && entries.has(id)
} Prevention
- Clear activeBackgroundId to 'none' whenever the referenced background is deleted
- Await store initialization before reading activeBackgroundUrl in non-reactive contexts
- Handle a null activeBackgroundUrl in the scene renderer as a supported state, not an error
When it happens
Trigger: activeBackgroundId points at a deleted journal/selfie background; the store's async initializeStore() has not hydrated entries yet (first render after boot); a cross-window deletion broadcast has not been applied in this window; or profile/card JSON was synced to a machine where the background blobs were never created.
Common situations: User deleted a journal image that was set as the active background; duplicated profiles across devices sharing card data but not IndexedDB blobs; races between app startup and the auto-init store; leftover IDs after the image-journal prefix migration.
Related errors
AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18).
Data as JSON: /api/errors/4f6a4421e68df3a2.
Report an issue: GitHub.