siyuan-note/siyuan · error

invalid provider config

Error message

invalid provider config

What it means

After unmarshalling and ai.Normalize(), resolveAIProvider expects exactly one provider to remain in the constructed conf.AI; if normalization dropped or duplicated the provider (len != 1), the inline config is considered structurally invalid and rejected.

Solutions

  1. Compare your providerConfig against a known-good saved provider (fetch one from settings/config) and match all required fields
  2. Log the provider struct before ai.Normalize() to see what Normalize drops or transforms
  3. Upgrade/downgrade concerns: check whether conf.Provider/Normalize semantics changed between versions and update the payload
  4. Send the provider ID via request.Provider instead of inline config if you mean to reference an already-saved provider

Example fix

// before: wrapper object unmarshals to zero providers
{"providerConfig": {"provider": {"baseURL": "https://api.openai.com"}}}
// after: flat provider object
{"providerConfig": {"baseURL": "https://api.openai.com", "key": "sk-..."}}
Defensive patterns

Strategy: validation

Validate before calling

ai := &conf.AI{Providers: []*conf.Provider{provider}}
ai.Normalize()
if len(ai.Providers) != 1 {
    return errors.New("invalid provider config")
}

Try / catch

provider, err := resolveAIProvider(req)
if err != nil {
    return contractFailure[string](gulu.Ret.NewResultWithMsg(err.Error()))
}

Prevention

When it happens

Trigger: An inline providerConfig that conf.AI.Normalize() discards — e.g. a provider failing normalization's validity checks (bad/missing fields beyond BaseURL), or a payload shape that unmarshals into zero or multiple providers.

Common situations: Partially filled provider configs from older versions whose fields no longer survive Normalize, API clients sending an unexpected providerConfig shape (array or wrapper object), config migrations leaving the provider in a state Normalize rejects.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19). Data as JSON: /api/errors/bb9cba44f304cdb9. Report an issue: GitHub.

Appendix: source

Thrown at kernel/api/ai.go:77

	if providerConfig := request.ProviderConfig; providerConfig != nil {
		data, err := gulu.JSON.MarshalJSON(providerConfig)
		if err != nil {
			return nil, err
		}
		provider := &conf.Provider{}
		if err = gulu.JSON.UnmarshalJSON(data, provider); err != nil {
			return nil, err
		}
		if strings.TrimSpace(provider.BaseURL) == "" {
			return nil, errors.New("provider base URL is required")
		}
		if err = util.ValidateAIProviderHeaders(provider.Headers); err != nil {
			return nil, err
		}
		ai := &conf.AI{Providers: []*conf.Provider{provider}}
		ai.Normalize()
		if len(ai.Providers) != 1 {
			return nil, errors.New("invalid provider config")
		}
		return ai.Providers[0], nil
	}

	providerID := request.Provider
	for _, provider := range model.Conf.AI.Providers {
		if provider != nil && provider.ID == providerID {
			return provider, nil
		}
	}
	return nil, errors.New("provider not found")
}

var chatGPT = contractHandler(apicontract.AIChatGPT, chatGPTContract)

func chatGPTContract(c *gin.Context, req apicontract.AIMessageRequest) apicontract.Response[string] {

	return apicontract.Success(model.ChatGPT(req.Msg))

View on GitHub (pinned to 9f775e8a12)