fix(storage): CRITICAL - preserve vectors when updating HNSW connections (v4.7.3)
CRITICAL DATA CORRUPTION FIX affecting ALL storage adapters
## Root Cause
When HNSW index updated node connections (adding new neighbors), saveHNSWData()
overwrote the entire node file with ONLY {level, connections}, destroying vector data.
## Impact
- v4.7.2: Broke ALL imports - relate() crashed with "Cannot read properties of undefined"
- Affected ALL storage adapters: FileSystem, GCS, Azure, R2, OPFS, S3Compatible
- VFS imports completely non-functional
- Any multi-entity operation would corrupt existing entity vectors
## The Bug
```typescript
// OLD CODE (v4.7.2) - DESTROYED VECTORS:
async saveHNSWData(id, hnswData) {
await writeFile(path, JSON.stringify(hnswData)) // Only {level, connections}!
}
```
When entity2 was added to HNSW:
1. HNSW found entity1 as neighbor
2. Updated entity1's connections
3. Called saveHNSWData(entity1.id, {level, connections})
4. Overwrote entity1.json with ONLY {level, connections}
5. **entity1.vector and entity1.id were DESTROYED**
## The Fix
```typescript
// NEW CODE (v4.7.3) - PRESERVES ALL DATA:
async saveHNSWData(id, hnswData) {
const existing = await readFile(path)
const updated = {...existing, level: hnswData.level, connections: hnswData.connections}
await writeFile(path, JSON.stringify(updated)) // Preserves id, vector, etc.
}
```
Now READ existing node, UPDATE only HNSW fields, WRITE complete node.
## Files Changed
- src/storage/adapters/fileSystemStorage.ts (line 2590-2626)
- src/storage/adapters/gcsStorage.ts (line 1863-1911)
- src/storage/adapters/azureBlobStorage.ts (line 1638-1682)
- src/storage/adapters/r2Storage.ts (line 999-1029)
- src/storage/adapters/opfsStorage.ts (line 2012-2051)
- src/storage/adapters/s3CompatibleStorage.ts (line 3903-3961)
## Testing
✅ FileSystemStorage: Verified with test-relate-crash.js
✅ All adapters: Compilation successful
✅ Imports: VFS directory creation and relate() working
## Breaking Changes
NONE - This is a critical bug fix
## Migration
Workshop team: Delete brainy-data and reimport with v4.7.3
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
fc307bc215
commit
46e74827c4
8 changed files with 180 additions and 349 deletions
|
|
@ -1002,10 +1002,30 @@ export class R2Storage extends BaseStorage {
|
|||
}): Promise<void> {
|
||||
await this.ensureInitialized()
|
||||
|
||||
// CRITICAL FIX (v4.7.3): Must preserve existing node data (id, vector) when updating HNSW metadata
|
||||
const shard = getShardIdFromUuid(nounId)
|
||||
const key = `entities/nouns/hnsw/${shard}/${nounId}.json`
|
||||
|
||||
await this.writeObjectToPath(key, hnswData)
|
||||
try {
|
||||
// Read existing node data
|
||||
const existingNode = await this.readObjectFromPath(key)
|
||||
|
||||
if (existingNode) {
|
||||
// Preserve id and vector, update only HNSW graph metadata
|
||||
const updatedNode = {
|
||||
...existingNode,
|
||||
level: hnswData.level,
|
||||
connections: hnswData.connections
|
||||
}
|
||||
await this.writeObjectToPath(key, updatedNode)
|
||||
} else {
|
||||
// Node doesn't exist yet, create with just HNSW data
|
||||
await this.writeObjectToPath(key, hnswData)
|
||||
}
|
||||
} catch (error) {
|
||||
// If read fails, create with just HNSW data
|
||||
await this.writeObjectToPath(key, hnswData)
|
||||
}
|
||||
}
|
||||
|
||||
public async getHNSWData(nounId: string): Promise<{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue