vxcontrol/pentagi · error

failed to bulk-update assistants provider name: %w

Error message

failed to bulk-update assistants provider name: %w

What it means

Raised inside reassignFlowsProvider when the bulk UPDATE of the assistants table — UpdateAssistantsProviderNameByOldName — fails while repointing a user's assistants from oldName to newName after a provider rename/deletion. Like the flows update, the SQL error is logged and wrapped as "failed to bulk-update assistants provider name: %w". Publishing of the provider-change event happens only after both writes complete so a wedged websocket subscriber cannot starve the second UPDATE.

Source

Thrown at backend/pkg/controller/flows.go:502

	flows, flowsErr := fc.db.UpdateFlowsProviderNameByOldName(ctx, database.UpdateFlowsProviderNameByOldNameParams{
		NewName: newName.String(),
		UserID:  userID,
		OldName: oldName.String(),
	})
	if flowsErr != nil {
		logger.WithError(flowsErr).Error("failed to bulk-update flows provider name")
		flowsErr = fmt.Errorf("failed to bulk-update flows provider name: %w", flowsErr)
	}

	assistants, asstErr := fc.db.UpdateAssistantsProviderNameByOldName(
		ctx, database.UpdateAssistantsProviderNameByOldNameParams{
			NewName: newName.String(),
			UserID:  userID,
			OldName: oldName.String(),
		})
	if asstErr != nil {
		logger.WithError(asstErr).Error("failed to bulk-update assistants provider name")
		asstErr = fmt.Errorf("failed to bulk-update assistants provider name: %w", asstErr)
	}

	// Publishing happens only after both writes are done. A subscriber that is
	// not draining its channel makes each publish cost up to the subscription
	// send timeout, so doing it in between would let a wedged websocket client
	// eat the deadline and starve the second UPDATE.
	for _, flow := range flows {
		// Skipped rather than published with no containers: FlowUpdated carries
		// the full terminal list and the client replaces its cached value with
		// whatever arrives, so an empty list would wipe the flow's terminals in
		// the UI. Same handling as flowWorker.switchProvider.
		containers, err := fc.db.GetFlowContainers(ctx, flow.ID)
		if err != nil {
			logger.WithError(err).Warnf("failed to get containers for flow %d, skipping its update event", flow.ID)
			continue
		}
		fc.subs.NewFlowPublisher(userID, flow.ID).FlowUpdated(ctx, flow, containers)
	}

View on GitHub (pinned to ea665308ba)

Solutions

  1. Check server logs for the logged underlying SQL error (asstErr is logged before wrapping).
  2. Retry the rename — both sweeps match only rows still bearing oldName, so the operation is idempotent.
  3. Investigate locks on the assistants table and concurrent transactions.
  4. Verify DB connectivity/pool health and consider increasing reassignProviderTimeout.

Example fix

null
Defensive patterns

Strategy: retry

Validate before calling

// verify the old provider name really no longer resolves to skip a pointless cascade
if _, err := provs.GetProvider(ctx, oldName, userID); err == nil {
    return nil // old name still resolves; nothing to reassign
}

Type guard

null

Try / catch

if err := flows.ResetFlowsProviderToDefault(ctx, userID, old, ptype); err != nil {
    if strings.Contains(err.Error(), "failed to bulk-update assistants provider name") {
        time.Sleep(backoff)
        err = flows.ResetFlowsProviderToDefault(ctx, userID, old, ptype)
    }
    return err
}

Prevention

When it happens

Trigger: Calling RenameFlowsProvider or ResetFlowsProviderToDefault when UPDATE assistants SET ... WHERE user_id=? AND provider_name=oldName fails: DB unreachable, lock contention, or the detached reassignProviderTimeout context expiring (possibly after a slow publish on the flows path).

Common situations: Provider rename in the settings UI hitting a temporarily unhealthy DB; row-level locks held by concurrent assistant writes; DB failover between the two UPDATE statements; timeout too small for a loaded database.

Related errors


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