vxcontrol/pentagi · error

pgvector store is not initialized

Error message

pgvector store is not initialized

What it means

Redundant defensive check inside memory.Handle: even though IsAvailable() passed at entry, the code re-verifies m.store is non-nil before executing any tool action, and errors if the pgvector store is nil. Reaching it means the store became nil or the availability check and this check disagree.

Source

Thrown at backend/pkg/tools/memory.go:55

		store:  store,
		vslp:   vslp,
	}
}

func (m *memory) Handle(ctx context.Context, name string, args json.RawMessage) (string, error) {
	if !m.IsAvailable() {
		return "", fmt.Errorf("memory is not available")
	}

	ctx, observation := obs.Observer.NewObservation(ctx)
	logger := logrus.WithContext(ctx).WithFields(enrichLogrusFields(m.flowID, nil, nil, logrus.Fields{
		"tool": name,
		"args": string(args),
	}))

	if m.store == nil {
		logger.Error("pgvector store is not initialized")
		return "", fmt.Errorf("pgvector store is not initialized")
	}

	switch name {
	case SearchInMemoryToolName:
		var action SearchInMemoryAction
		if err := json.Unmarshal(args, &action); err != nil {
			logger.WithError(err).Error("failed to unmarshal search in memory action arguments")
			return "", fmt.Errorf("failed to unmarshal %s search in memory action arguments: %w", name, err)
		}

		filters := map[string]any{
			"flow_id":  strconv.FormatInt(m.flowID, 10),
			"doc_type": memoryVectorStoreDefaultType,
		}
		if action.TaskID != nil && *action.TaskID != 0 {
			filters["task_id"] = action.TaskID.String()
		}
		if action.SubtaskID != nil && *action.SubtaskID != 0 {

View on GitHub (pinned to ea665308ba)

Solutions

  1. Ensure NewMemoryTool is never called with a nil *pgvector.Store.
  2. Keep IsAvailable() consistent with the nil-store check (default implementation returns store != nil).
  3. Check startup ordering so the pgvector store is fully initialized before tools are created.
  4. If this fires in production, inspect for code that nils out or replaces the store at runtime.
Defensive patterns

Strategy: type-guard

Validate before calling

if m.store == nil {
    return errors.New("pgvector store missing; configure the vector store before using memory tools")
}

Type guard

func (m *memory) ready() bool { return m.store != nil }

func ensureMemory(m Tool) (*memory, bool) {
    mm, ok := m.(*memory)
    return mm, ok && mm.ready()
}

Try / catch

out, err := tool.Handle(ctx, "search_in_memory", args)
if err != nil && strings.Contains(err.Error(), "pgvector store is not initialized") {
    log.Println("pgvector store unavailable; skipping memory search")
    return memoryNotFoundMessage, nil
}

Prevention

When it happens

Trigger: Calling search_in_memory when memory.store is nil despite IsAvailable() returning true (e.g. custom implementations overriding IsAvailable, or store mutated/cleared after construction); in stock code this is effectively unreachable unless NewMemoryTool was handed a nil store with an availability override.

Common situations: Custom Tool wrappers reimplementing IsAvailable; tests constructing memory with a nil store; concurrent reinitialization setting the store to nil.

Related errors


AI-assisted analysis of vxcontrol/pentagi@ea665308ba (2026-09-01). Data as JSON: /api/errors/c23fcb7e56fcb14e. Report an issue: GitHub.