vxcontrol/pentagi · error

failed to marshal provider config: %w

Error message

failed to marshal provider config: %w

What it means

After validation, UpdateProvider serializes the config with json.Marshal before persisting it. A failure here is wrapped as "failed to marshal provider config: %w". In practice json.Marshal of this struct essentially never fails unless the config contains an unsupported value (e.g. a channel, func, or a custom MarshalJSON returning an error).

Source

Thrown at backend/pkg/providers/providers.go:797

		ID:     prvID,
		UserID: userID,
	})
	if err != nil {
		return result, fmt.Errorf("failed to get provider: %w", err)
	}
	prvtype := provider.ProviderType(prv.Type)

	if config, err = pc.patchProviderConfig(prvtype, config); err != nil {
		return result, fmt.Errorf("failed to patch provider config: %w", err)
	}

	if err = config.Validate(); err != nil {
		return result, fmt.Errorf("invalid provider config: %w", err)
	}

	rawConfig, err := json.Marshal(config)
	if err != nil {
		return result, fmt.Errorf("failed to marshal provider config: %w", err)
	}

	result, err = pc.db.UpdateUserProvider(ctx, database.UpdateUserProviderParams{
		ID:     prvID,
		UserID: userID,
		Name:   string(prvname),
		Config: rawConfig,
	})
	if err != nil {
		return result, fmt.Errorf("failed to update provider: %w", err)
	}

	return result, nil
}

func (pc *providerController) DeleteProvider(
	ctx context.Context,
	userID int64,

View on GitHub (pinned to ea665308ba)

Solutions

  1. Inspect the wrapped inner error to identify which field breaks marshaling
  2. Check for recently added fields on pconfig.ProviderConfig with unsupported types (chan, func, sync primitives)
  3. Add json:"..." tags / omit unsupported fields or make them serializable
  4. If a custom MarshalJSON exists on a nested type, fix its error path

Example fix

// before
Config: someField: make(chan int)   // unserializable field in ProviderConfig
// after
Config: someField: nil              // or replace with a serializable representation
Defensive patterns

Strategy: try-catch

Validate before calling

if _, err := json.Marshal(config); err != nil {
    return fmt.Errorf("config not serializable: %w", err)
}

Try / catch

result, err := ctrl.UpdateProvider(ctx, userID, prvID, name, cfg)
if err != nil && strings.Contains(err.Error(), "failed to marshal provider config") {
    return fmt.Errorf("config contains an unsupported field value: %w", err)
}

Prevention

When it happens

Trigger: json.Marshal(config) returns an error inside UpdateProvider — e.g. a field in pconfig.ProviderConfig carries an unsupported type or a custom MarshalJSON implementation fails.

Common situations: A recent code change added a non-serializable field to ProviderConfig; a custom marshaller on a nested type returns an error; corrupted in-memory config built programmatically.

Understand the failure class

Background: json.Marshal / "failed to marshal" errors in Go: why "unsupported type" happens and how to fix it — this error's family across 22 libraries.

Related errors


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