{"record":{"id":"d8a66319e9bd90d8","repo":"weaviate/weaviate","slug":"w-discriminant-size-d-expected-d-for-level-d-d8a663","errorCode":null,"errorMessage":"%w: discriminant size %d, expected %d for level %d","messagePattern":"%w: discriminant size (.+?), expected (.+?) for level (.+?)","errorType":"exception","errorClass":"ErrIllegalArguments","httpStatus":null,"severity":"error","filePath":"usecases/replica/hashtree/hashtree.go","lineNumber":215,"sourceCode":"func (ht *HashTree) Level(level int, discriminant *Bitset, digests []Digest) (n int, err error) {\n\tht.mux.Lock()\n\tdefer ht.mux.Unlock()\n\n\tif level < 0 {\n\t\treturn 0, fmt.Errorf(\"%w: invalid level(%d)\", ErrIllegalArguments, level)\n\t}\n\n\tif level > ht.Height() {\n\t\treturn 0, fmt.Errorf(\"%w: level(%d) is too high for current height(%d)\", ErrIllegalState, level, ht.height)\n\t}\n\n\tif discriminant == nil {\n\t\treturn 0, fmt.Errorf(\"%w: nil discriminant provided\", ErrIllegalArguments)\n\t}\n\n\texpectedSize := nodesAtLevel(level)\n\tif discriminant.Size() != expectedSize {\n\t\treturn 0, fmt.Errorf(\"%w: discriminant size %d, expected %d for level %d\",\n\t\t\tErrIllegalArguments, discriminant.Size(), expectedSize, level)\n\t}\n\n\t// one digest is written per set bit, so SetCount() capacity suffices (see LevelDiff)\n\tif len(digests) < discriminant.SetCount() {\n\t\treturn 0, fmt.Errorf(\"%w: output buffer has not enough capacity\", ErrIllegalArguments)\n\t}\n\n\tht.sync()\n\n\toffset := InnerNodesCount(level)\n\n\tfor i := 0; i < expectedSize; i++ {\n\t\tif discriminant.IsSet(i) {\n\t\t\t// bound writes even if the cached set count understates the bits\n\t\t\tif n == len(digests) {\n\t\t\t\treturn 0, fmt.Errorf(\"%w: discriminant set count understates its set bits\", ErrIllegalArguments)\n\t\t\t}","sourceCodeStart":197,"sourceCodeEnd":233,"githubUrl":"https://github.com/weaviate/weaviate/blob/75aa4b6d11f8818305aafd4440b4e32794f7ca04/usecases/replica/hashtree/hashtree.go#L197-L233","documentation":"HashTree.Level() expects a level-local discriminant whose Size() exactly equals the number of nodes at that level (nodesAtLevel(level)). Bit i selects node i, so a wrong size means bit indices are ambiguous. The library throws ErrIllegalArguments to prevent misaligned selection masks.","triggerScenarios":"Passing a leaf-level discriminant (Size()==LeavesCount(height)) into Level for an inner level, or vice versa; reusing a walk bitset from a different tree height; calling Level on trees of different heights with the same Bitset.","commonSituations":"Using a discriminant produced by Diff (leaf-level) directly with Level(level,...) for level < Height(); caching bitsets across trees whose heights changed after a schema/shard change; confusion between LeavesCount and nodesAtLevel sizes.","solutions":["Build the discriminant with exactly NewBitset(nodesAtLevel(level)) bits for the level you query.","If you only have a leaf-level discriminant, derive the per-level mask yourself, or use Diff/NewRangeReader which handle level-local masks internally.","Verify both trees involved have identical Height() before sharing bitsets between them."],"exampleFix":"// before\ndisc := hashtree.NewBitset(ht.LeavesCount(height)) // leaf-level size\nht.Level(l, disc, digests)\n// after\ndisc := hashtree.NewBitset(nodesAtLevel(l)) // level-local size\nht.Level(l, disc, digests)","handlingStrategy":"validation","validationCode":"if disc != nil && disc.Size() != nodesAtLevel(level) {\n    return fmt.Errorf(\"discriminant size %d != %d for level %d\", disc.Size(), nodesAtLevel(level), level)\n}","typeGuard":"func isLevelLocalDisc(disc *hashtree.Bitset, level int) bool {\n    return disc != nil && disc.Size() == nodesAtLevel(level)\n}","tryCatchPattern":null,"preventionTips":["Build level-local masks with NewBitset(nodesAtLevel(level)) per queried level","Never reuse leaf-level Diff output as a Level() discriminant for inner levels","Share bitsets only between trees of identical Height()"],"tags":["go","hashtree","argument-validation","bitset-size"],"backgroundTag":"bitset-size-mismatch","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"}