siyuan-note/siyuan · error
invalid provider config
Error message
invalid provider config
What it means
After accepting an inline providerConfig, resolveAIProvider runs it through conf.AI.Normalize() and then asserts the provider list still contains exactly one entry (kernel/api/ai.go:54-58). Normalize pruns nil entries and repairs malformed fields (empty baseURL is defaulted, bad IDs regenerated — conf/ai.go:588-631); a count change therefore means the submitted providerConfig was structurally invalid in a way normalization rejects, and the request fails with 'invalid provider config' rather than proceeding with a mutated provider.
Source
Thrown at kernel/api/ai.go:57
}
func resolveAIProvider(arg map[string]any) (*conf.Provider, error) {
if providerConfig, ok := arg["providerConfig"]; ok && 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")
}
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, _ := arg["provider"].(string)
for _, provider := range model.Conf.AI.Providers {
if provider != nil && provider.ID == providerID {
return provider, nil
}
}
return nil, errors.New("provider not found")
}
func chatGPT(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)
arg, ok := util.JsonArg(c, ret)View on GitHub (pinned to afa823b6b4)
Solutions
- Send a fully-formed provider object: non-empty baseURL plus name/models; avoid empty shells
- If it appears right after a SiYuan version change, re-save the provider via the AI settings UI so the kernel re-normalizes persisted config
- For plugin authors calling resolveAIProvider-shaped flows, construct conf.Provider with all required fields rather than partial structs
- Compare the payload against conf.Provider JSON tags before submitting
Example fix
// before
{"providerConfig": {}}
// after
{"providerConfig": {"baseURL": "https://api.openai.com/v1", "apiKey": "sk-x", "models": [{"name": "gpt-4o"}]}} Defensive patterns
Strategy: validation
Validate before calling
const okProviderConfig = (p: any) =>
!!p && typeof p === 'object' && !Array.isArray(p) &&
typeof p.baseURL === 'string' && p.baseURL.trim() !== '' &&
(!p.models || Array.isArray(p.models));
if (!okProviderConfig(req.providerConfig)) throw new Error('invalid provider config'); Type guard
const isProviderConfig = (p: unknown): p is Record<string, any> => !!p && typeof p === 'object' && !Array.isArray(p) && typeof (p as any).baseURL === 'string' && (p as any).baseURL.trim() !== '';
Try / catch
null
Prevention
- Send fully-formed provider objects; never empty shells or null-ish providerConfig values
- After upgrading SiYuan, re-save providers in Settings - AI so persisted config re-normalizes
- For plugin authors, populate every required conf.Provider field programmatically
When it happens
Trigger: providerConfig marshals to something that unmarshals into conf.Provider yet normalizes away — in practice a nil/empty provider sneaking through (e.g. providerConfig passed as a JSON null-ish value that survives the earlier nil check, or a provider entry Normalize drops as nil in a future rule). Normal single-object payloads with a baseURL never hit it; they pass or fail earlier checks.
Common situations: Defensive canary firing after a conf.AI.Normalize() rule change adds new pruning (version upgrade between frontend and kernel); clients sending providerConfig: {} variants; plugin code constructing Provider structs programmatically with zero values.
Related errors
- provider base URL is required
- provider not found
- unknown cloud provider [%d]
- invalid provider [%d]
- opened notebook [%s] not found
AI-assisted analysis of siyuan-note/siyuan@afa823b6b4 (2026-08-18).
Data as JSON: /api/errors/bb9cba44f304cdb9.
Report an issue: GitHub.