{"record":{"id":"d2de6e0c74d4af94","repo":"weaviate/weaviate","slug":"update-inverted-indices","errorCode":null,"errorMessage":"update inverted indices","messagePattern":"update inverted indices","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"adapters/repos/db/shard_write_merge.go","lineNumber":219,"sourceCode":"\t\t}\n\n\t\t// Tee before hashtree: the bucket is the SSOT for movement catchup.\n\t\t// This path does NOT funnel through putObjectLSM, so it needs its own tee.\n\t\ts.AppendChangeLogPut(idBytes, obj.LastUpdateTimeUnix(), objBytes)\n\n\t\tif err := s.mayUpsertObjectHashTree(obj, idBytes, status); err != nil {\n\t\t\treturn errors.Wrap(err, \"object merge in hashtree\")\n\t\t}\n\n\t\treturn nil\n\t}(); err != nil {\n\t\treturn nil, objectInsertStatus{}, err\n\t} else if status.skipUpsert {\n\t\treturn obj, status, nil\n\t}\n\n\tif err := s.updateInvertedIndexLSM(obj, status, prevObj); err != nil {\n\t\treturn nil, status, errors.Wrap(err, \"update inverted indices\")\n\t}\n\n\treturn obj, status, nil\n}\n\n// mutableMergeObjectLSM is a special version of mergeObjectInTx where no doc\n// id increases will be made, but instead the old doc ID will be re-used. This\n// is only possible if the following two conditions are met:\n//\n//  1. We only add to the inverted index, but there is nothing which requires\n//     cleaning up. Example `name: \"John\"` is updated to `name: \"John Doe\"`,\n//     this is valid because we only add new entry for \"Doe\", but do not alter\n//     the existing entry for \"John\"\n//     An invalid update would be `name:\"John\"` is updated to `name:\"Diane\"`,\n//     this would require a cleanup for the existing link from \"John\" to this\n//     doc id, which is not possible. The only way to clean up is to increase\n//     the doc id and delete all entries for the old one\n//","sourceCodeStart":201,"sourceCodeEnd":237,"githubUrl":"https://github.com/weaviate/weaviate/blob/75aa4b6d11f8818305aafd4440b4e32794f7ca04/adapters/repos/db/shard_write_merge.go#L201-L237","documentation":"Wrapper around s.updateInvertedIndexLSM(obj, status, prevObj) at the end of mergeObjectInStorage. After the object and vectors are persisted, the inverted (filter) index must be updated to add new property-term entries and remove stale ones for the old doc ID. A failure here means the object was stored but its filterable index may now be stale or partially updated — searches on the affected properties may return wrong results until repaired.","triggerScenarios":"PATCH merge that changes filterable property values (or adds/removes references) where the LSM set/map buckets of the inverted index fail to write: disk full, bucket closed during class/tenant deletion, or I/O error.","commonSituations":"Disk pressure on nodes with heavy filterable payloads; concurrent tenant offload or collection deletion racing a PATCH; large reference arrays triggering big inverted-index writes.","solutions":["Check disk space/I-O health on the shard's volume","Retry the PATCH after storage recovers","Verify filter queries on the merged properties; force a re-index/repair of the shard if results are inconsistent","Check for concurrent delete/offload operations and re-run after they finish"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// verify the merged properties are filterable/declared in the schema\nfor _, prop := range changedProps {\n    if !isDeclaredProperty(class, prop) {\n        return fmt.Errorf(\"property %q not in schema; inverted index cannot be updated\", prop)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := mergeObject(ctx, class, id, patch); err != nil {\n    if strings.Contains(err.Error(), \"update inverted indices\") {\n        // object may be stored but filter index stale: verify then repair\n        repairInvertedIndex(ctx, class, shard)\n        return fmt.Errorf(\"merge partially applied, index repair triggered: %v\", err)\n    }\n    return err\n}","preventionTips":["Only patch properties declared with invertedIndexConfig enabled as needed","Keep disk headroom; large reference arrays blow up inverted-index writes","Re-run affected filter queries after any merge error to detect staleness","Schedule index repairs after storage incidents"],"tags":["inverted-index","storage","filtering","merge"],"backgroundTag":"inverted-index-update-failed","analyzedSha":"75aa4b6d11f8818305aafd4440b4e32794f7ca04","analyzedAt":"2026-09-04T14:58:20.392Z","contentChangedAt":"2026-09-04T14:58:20.392Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}