weaviate/weaviate · error

tempVectorForIDWithViewThunk cannot be nil

Error message

tempVectorForIDWithViewThunk cannot be nil

What it means

hfresh Config.Validate requires a TempVectorForIDWithViewThunk — the function used to materialize temporary vectors through a storage view — to be non-nil. HFresh cannot read vectors during centroid/posting operations without it, so a nil thunk makes the config invalid and index construction aborts.

Source

Thrown at adapters/repos/db/vector/hfresh/config.go:85

	DefaultReassignNeighbors         = 8
	DefaultMaxDistanceRatio          = 10_000
)

func (c *Config) Validate() error {
	c.Logger = common.LoggerOrDiscard(c.Logger)

	if c.InternalPostingCandidates <= 0 {
		c.InternalPostingCandidates = DefaultInternalPostingCandidates
	}
	if c.ReassignNeighbors <= 0 {
		c.ReassignNeighbors = DefaultReassignNeighbors
	}
	if c.MaxDistanceRatio <= 0 {
		c.MaxDistanceRatio = DefaultMaxDistanceRatio
	}

	if c.TempVectorForIDWithViewThunk == nil {
		return errors.New("tempVectorForIDWithViewThunk cannot be nil")
	}

	if c.VectorForIDThunk == nil {
		return errors.New("vectorForIDThunk cannot be nil")
	}

	return nil
}

func DefaultConfig() *Config {
	return &Config{
		Logger:                    logrus.New(),
		InternalPostingCandidates: DefaultInternalPostingCandidates,
		ReassignNeighbors:         DefaultReassignNeighbors,
		MaxDistanceRatio:          DefaultMaxDistanceRatio,
		DistanceProvider:          distancer.NewL2SquaredProvider(),
		Store:                     StoreConfig{MakeBucketOptions: lsmkv.MakeRegularBucketOptions},
	}

View on GitHub (pinned to 75aa4b6d11)

Solutions

  1. Set c.TempVectorForIDWithViewThunk to the shard's view-based vector accessor before calling New/Validate.
  2. Start from DefaultConfig() and assign both thunks rather than building Config from scratch.
  3. If constructing in tests, reuse the same wiring the shard code uses to build the thunk.
  4. Validate the config early at call sites so the nil thunk is caught before index creation proceeds.

Example fix

// before
cfg := hfresh.DefaultConfig()
cfg.VectorForIDThunk = store.VectorForIDThunk
// after
cfg := hfresh.DefaultConfig()
cfg.VectorForIDThunk = store.VectorForIDThunk
cfg.TempVectorForIDWithViewThunk = store.TempVectorForIDWithViewThunk
Defensive patterns

Strategy: validation

Validate before calling

if cfg.TempVectorForIDWithViewThunk == nil {
    return errors.New("hfresh config: TempVectorForIDWithViewThunk must be set")
}
if err := cfg.Validate(); err != nil {
    return err
}

Type guard

func validHFreshConfig(c *hfresh.Config) bool {
    return c != nil &&
        c.TempVectorForIDWithViewThunk != nil &&
        c.VectorForIDThunk != nil
}

Try / catch

if err := cfg.Validate(); err != nil {
    if strings.Contains(err.Error(), "tempVectorForIDWithViewThunk") {
        return fmt.Errorf("config wiring bug: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Building an HFresh index (New(...) -> Config.Validate) from a Config assembled manually or programmatically where TempVectorForIDWithViewThunk was never assigned.

Common situations: Custom/programmatic index construction in tests or internal tooling; wiring bug where only VectorForIDThunk was set; using DefaultConfig() (which leaves thunks nil) without filling them in.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


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