moeru-ai/airi · warning
property key 'version' wasn't found in the value of key ${ke
Error message
property key 'version' wasn't found in the value of key ${key} as ${value}, will keep the current ${toValue(initialValue)} What it means
The same composable requires stored values to carry a top-level 'version' property. When the parsed JSON for the key has no version field, it cannot be version-checked, so the value is treated as unrecognizable: storage and data are reset to { version: defaultVersion, data: initialValue } with this warning naming the offending raw value.
Source
Thrown at packages/stage-shared/src/composables/use-versioned-local-storage/index.ts:67
syncDataToStorage.resume()
}
}
else {
console.warn(`version ${rawValue.value.version} doesn't satisfy the version ${defaultVersion} for key ${key}, will reset the value to default value ${toValue(initialValue)}`)
rawValue.value = { version: defaultVersion, data: toValue(initialValue) }
syncDataToStorage.pause()
data.value = toValue(initialValue)
syncDataToStorage.resume()
}
}
syncDataToStorage.pause()
data.value = rawValue.value.data!
syncDataToStorage.resume()
return
}
console.warn(`property key 'version' wasn't found in the value of key ${key} as ${value}, will keep the current ${toValue(initialValue)}`)
rawValue.value = { version: defaultVersion, data: toValue(initialValue) }
syncDataToStorage.pause()
data.value = toValue(initialValue)
syncDataToStorage.resume()
}
catch (err) {
console.warn(`failed to un-marshal Local Storage value, possibly due to incompatible or corrupted for key ${key} value ${value}, falling back to default value ${toValue(initialValue)}`, err)
rawValue.value = { version: defaultVersion, data: toValue(initialValue) }
syncDataToStorage.pause()
data.value = toValue(initialValue)
syncDataToStorage.resume()
}
}, {
immediate: true,
deep: true,
})
return dataView on GitHub (pinned to 677329427f)
Solutions
- Use a new (or newly prefixed) storage key when introducing versioning, so legacy plain values are never read
- Pre-migrate on first run: read the raw value yourself, and if it lacks a version, wrap it into the envelope before the composable initializes
- Keep localStorage keys unique per feature to avoid cross-writers
Example fix
// before
const { data } = useVersionedLocalStorage('settings', defaults, { version: 1 })
// legacy key holds { theme: 'dark' } without version -> resets to defaults
// after
const legacy = localStorage.getItem('settings')
if (legacy && !('version' in JSON.parse(legacy))) {
localStorage.setItem('settings', JSON.stringify({ version: 1, data: JSON.parse(legacy) }))
}
const { data } = useVersionedLocalStorage('settings', defaults, { version: 1 }) Defensive patterns
Strategy: validation
Validate before calling
const raw = localStorage.getItem(key)
if (raw) {
const parsed = JSON.parse(raw)
if (!('version' in parsed)) {
// legacy value: wrap it into the envelope before the composable reads it
localStorage.setItem(key, JSON.stringify({ version: 1, data: parsed }))
}
} Type guard
function hasVersionField(value: unknown): value is { version: unknown } {
return typeof value === 'object' && value !== null && 'version' in value
} Prevention
- Use a fresh key or prefix when introducing versioned storage
- Never share one localStorage key between unrelated features
- On first deploy of versioning, run a one-time legacy-to-envelope migration
When it happens
Trigger: A localStorage key written by an older unversioned implementation, another feature using the same key with plain JSON, or hand-edited/devtools-modified storage lacking the envelope.
Common situations: Introducing use-versioned-local-storage on a key that previously stored a plain object; key collisions between features; stale values from a pre-release build.
Related errors
- version ${rawValue.value.version} doesn't satisfy the versio
- Widgets element not found
- useReplayable must be used within a Replayable component
AI-assisted analysis of moeru-ai/airi@677329427f (2026-08-18).
Data as JSON: /api/errors/12c6476f2defdd31.
Report an issue: GitHub.