weaviate/weaviate · critical

update inverted indices

Error message

update inverted indices

What it means

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.

Source

Thrown at adapters/repos/db/shard_write_merge.go:219

		}

		// Tee before hashtree: the bucket is the SSOT for movement catchup.
		// This path does NOT funnel through putObjectLSM, so it needs its own tee.
		s.AppendChangeLogPut(idBytes, obj.LastUpdateTimeUnix(), objBytes)

		if err := s.mayUpsertObjectHashTree(obj, idBytes, status); err != nil {
			return errors.Wrap(err, "object merge in hashtree")
		}

		return nil
	}(); err != nil {
		return nil, objectInsertStatus{}, err
	} else if status.skipUpsert {
		return obj, status, nil
	}

	if err := s.updateInvertedIndexLSM(obj, status, prevObj); err != nil {
		return nil, status, errors.Wrap(err, "update inverted indices")
	}

	return obj, status, nil
}

// mutableMergeObjectLSM is a special version of mergeObjectInTx where no doc
// id increases will be made, but instead the old doc ID will be re-used. This
// is only possible if the following two conditions are met:
//
//  1. We only add to the inverted index, but there is nothing which requires
//     cleaning up. Example `name: "John"` is updated to `name: "John Doe"`,
//     this is valid because we only add new entry for "Doe", but do not alter
//     the existing entry for "John"
//     An invalid update would be `name:"John"` is updated to `name:"Diane"`,
//     this would require a cleanup for the existing link from "John" to this
//     doc id, which is not possible. The only way to clean up is to increase
//     the doc id and delete all entries for the old one
//

View on GitHub (pinned to 75aa4b6d11)

Solutions

  1. Check disk space/I-O health on the shard's volume
  2. Retry the PATCH after storage recovers
  3. Verify filter queries on the merged properties; force a re-index/repair of the shard if results are inconsistent
  4. Check for concurrent delete/offload operations and re-run after they finish
Defensive patterns

Strategy: try-catch

Validate before calling

// verify the merged properties are filterable/declared in the schema
for _, prop := range changedProps {
    if !isDeclaredProperty(class, prop) {
        return fmt.Errorf("property %q not in schema; inverted index cannot be updated", prop)
    }
}

Try / catch

if err := mergeObject(ctx, class, id, patch); err != nil {
    if strings.Contains(err.Error(), "update inverted indices") {
        // object may be stored but filter index stale: verify then repair
        repairInvertedIndex(ctx, class, shard)
        return fmt.Errorf("merge partially applied, index repair triggered: %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of weaviate/weaviate@75aa4b6d11 (2026-09-04). Data as JSON: /api/errors/d2de6e0c74d4af94. Report an issue: GitHub.