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 character

View on GitHub (pinned to 677329427f)

Solutions

  1. If this fires once at startup, ignore it - hydration finishes asynchronously and the computed re-evaluates
  2. If persistent, reset the stale reference: set extensions.airi.modules.activeBackgroundId to 'none' or to an ID present in getCharacterBackgrounds
  3. Re-create the missing background (re-upload or re-journal the image) so entries.value.has(lookupId) becomes true
  4. 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

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.