vxcontrol/pentagi · error

failed to switch provider: %w

Error message

failed to switch provider: %w

What it means

PutInput wraps an error from fw.switchProvider(ctx, prv) — the step that reconfigures the flow worker to use the requested LLM provider before processing user input. If the provider cannot be switched (provider unavailable, not configured, or construction fails), the input is rejected and resources are never queued.

Source

Thrown at backend/pkg/controller/flow.go:653

	return assistants
}

func (fw *flowWorker) ListTasks(ctx context.Context) []TaskWorker {
	return fw.tc.ListTasks(ctx)
}

func (fw *flowWorker) PutInput(
	ctx context.Context,
	input string,
	prv provider.Provider,
	resources []database.UserResource,
) error {
	ctx, span := obs.Observer.NewSpan(ctx, obs.SpanKindInternal, "controller.flowWorker.PutInput")
	defer span.End()

	if err := fw.switchProvider(ctx, prv); err != nil {
		return fmt.Errorf("failed to switch provider: %w", err)
	}

	if err := fw.PutResources(ctx, resources); err != nil {
		fw.logger.WithError(err).Warn("failed to copy resources before user input")
	}

	flin := flowInput{input: input, done: make(chan error, 1)}
	select {
	case <-fw.ctx.Done():
		close(flin.done)
		return fmt.Errorf("flow %d stopped: %w", fw.flowCtx.FlowID, fw.ctx.Err())
	case <-ctx.Done():
		close(flin.done)
		return fmt.Errorf("flow %d input processing timeout: %w", fw.flowCtx.FlowID, ctx.Err())
	case fw.input <- flin:
		timer := time.NewTimer(flowInputTimeout)
		defer timer.Stop()

View on GitHub (pinned to ea665308ba)

Solutions

  1. Read the wrapped error to see whether the provider is unregistered, unconfigured, or rejected credentials.
  2. Verify the provider type is whitelisted in pkg/server/models/providers.go Valid() and registered in pkg/providers/providers.go.
  3. Set the provider's API key/server URL in settings or env (e.g. OPENAI_API_KEY) and retry PutInput.
  4. Validate the provider name before calling PutInput; fall back to the flow's current provider if switching is optional.

Example fix

// before
err := fw.PutInput(ctx, "gpt99-turbo", input, resources) // unknown provider
// after
if provider.IsValid(prv) {
    err = fw.PutInput(ctx, prv, input, resources)
} else {
    err = fmt.Errorf("unsupported provider %q", prv)
}
Defensive patterns

Strategy: validation

Validate before calling

func providerConfigured(prv string) error {
    if !servermodels.ProviderType(prv).Valid() {
        return fmt.Errorf("unsupported provider %q", prv)
    }
    if _, err := providers.GetProvider(prv); err != nil {
        return fmt.Errorf("provider not available: %w", err)
    }
    return nil
}
// call before PutInput
if err := providerConfigured(prv); err != nil { return err }

Type guard

func isKnownProvider(prv string) bool {
    _, err := providers.GetProvider(prv)
    return err == nil
}

Try / catch

if err := fw.PutInput(ctx, prv, input, res); err != nil {
    if strings.Contains(err.Error(), "failed to switch provider") {
        // fall back to the flow's current provider or surface a config error to the user
        return fmt.Errorf("provider %q unavailable: %w", prv, err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling PutInput with a provider value that fails switchProvider: the provider name/type is not registered, its API key is missing, the provider adapter failed to initialize, or the provider's credential check errors.

Common situations: User selected an LLM provider in the UI that was later removed or whose API key was cleared from settings; typo in provider name passed via REST/GraphQL; provider type not whitelisted in Valid(); environment variable for the provider missing.

Related errors


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