siyuan-note/siyuan · error
provider base URL is required
Error message
provider base URL is required
What it means
resolveAIProvider, when given an inline providerConfig, requires a non-blank BaseURL on the provider. After unmarshalling the supplied config into conf.Provider, an empty base URL means no API endpoint is known, so the request is refused before any network call.
Solutions
- Set the provider's baseURL to the full API endpoint (e.g. https://api.openai.com) and retry
- Check field-name casing in the JSON payload — it must map to conf.Provider's BaseURL tag
- If switching from providerID reference to inline config, copy the BaseURL from the existing saved provider
- Verify with a request containing only baseURL to isolate the field mapping
Example fix
// before
{"providerConfig": {"name": "my-openai", "key": "sk-..."}}
// after
{"providerConfig": {"name": "my-openai", "baseURL": "https://api.openai.com", "key": "sk-..."}} Defensive patterns
Strategy: validation
Validate before calling
if strings.TrimSpace(provider.BaseURL) == "" {
return errors.New("provider base URL is required")
} Type guard
func hasBaseURL(p *conf.Provider) bool { return p != nil && strings.TrimSpace(p.BaseURL) != "" } Try / catch
provider, err := resolveAIProvider(req)
if err != nil {
return contractFailure[string](gulu.Ret.NewResultWithMsg(err.Error()))
} Prevention
- Require the API endpoint field in provider settings UI before saving
- Validate baseURL client-side before sending ProviderConfig
- Match JSON field names to conf.Provider's tags exactly
When it happens
Trigger: Calling an AI endpoint (e.g. the test-model or list-models contract APIs) with request.ProviderConfig whose baseURL/baseUrl field is empty, whitespace-only, or omitted entirely.
Common situations: User adds a custom AI provider in settings but leaves the API endpoint field blank, an API client builds ProviderConfig without baseURL, or migrating configs where the URL field was renamed and no longer maps.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- AI editor action must not be empty
- invalid provider config
- AI editor action not found
- AI editor input is empty
- Argon2id Iterations too high (maximum 10)
AI-assisted analysis of siyuan-note/siyuan@9f775e8a12 (2026-09-19).
Data as JSON: /api/errors/5b1d6608569497d4.
Report an issue: GitHub.
Appendix: source
Thrown at kernel/api/ai.go:69
}
return nil
}
func resolveAIProvider(request apicontract.AIProviderRequest) (*conf.Provider, error) {
if err := request.ProviderError(); err != nil {
return nil, err
}
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
}
}View on GitHub (pinned to 9f775e8a12)