siyuan-note/siyuan · error
list models HTTP %d: %s
Error message
list models HTTP %d: %s
What it means
The normal error path for ListAvailableModelsWithContext when GET /models returns non-2xx with a readable body. The message includes the HTTP status code and the trimmed response body (the provider's error JSON/text), giving the user the upstream's actual reason.
Source
Thrown at kernel/util/openai.go:360
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil)
if err != nil {
return nil, err
}
if apiKey != "" {
req.Header.Set("Authorization", "Bearer "+apiKey)
}
resp, err := httpclient.NewUserAgentClient(nil).Do(req)
if err != nil {
logging.LogErrorf("list models [%s] failed: %s", apiBaseURL, err)
return
}
defer resp.Body.Close()
if resp.StatusCode < http.StatusOK || http.StatusBadRequest <= resp.StatusCode {
body, readErr := io.ReadAll(io.LimitReader(resp.Body, 64*1024))
if readErr != nil {
err = fmt.Errorf("list models HTTP %d", resp.StatusCode)
} else {
err = fmt.Errorf("list models HTTP %d: %s", resp.StatusCode, strings.TrimSpace(string(body)))
}
logging.LogErrorf("list models [%s] failed: %s", apiBaseURL, err)
return
}
payload := &availableModelsPayload{}
if err = json.NewDecoder(resp.Body).Decode(payload); err != nil {
logging.LogErrorf("decode models [%s] failed: %s", apiBaseURL, err)
return
}
for _, item := range payload.Data {
id := strings.TrimSpace(item.ID)
if id == "" {
continue
}
models = append(models, AvailableModel{
ID: id,
ContextLength: firstValidModelContextLength(View on GitHub (pinned to 251596fc0d)
Solutions
- For 401/403: re-enter the API key in settings and verify it works in the provider's console.
- For 404: set apiBaseURL to the provider base (e.g. https://api.openai.com/v1), not the chat/completions path.
- For 429: wait and lower request rate; check quota/billing.
- For 5xx: check the provider status page and retry later.
Example fix
# before: apiBaseURL = https://api.openai.com/v1/chat/completions # -> 404 list models HTTP 404: ... # after: apiBaseURL = https://api.openai.com/v1
Defensive patterns
Strategy: try-catch
Validate before calling
if !strings.Contains(apiBaseURL, "/v1") && isOpenAICompatible {
log.Warn("apiBaseURL usually needs a /v1 suffix for the /models endpoint")
} Try / catch
if _, err := util.ListAvailableModelsWithContext(key, base, 30); err != nil {
// err.Error() already contains status + provider reason; surface it
return err
} Prevention
- Store API keys in settings, not in code
- Confirm apiBaseURL ends at the version root (e.g. /v1)
- Keep a known-working key in the provider console to cross-check
When it happens
Trigger: 401 invalid/expired API key; 403 region/org blocked; 404 wrong apiBaseURL (missing /v1 or wrong host); 422 provider rejects the request shape; 429 rate limit; 5xx provider outage.
Common situations: Typo in API key; apiBaseURL set to the chat endpoint instead of the base; using an OpenAI key against a non-compatible provider; free-tier quota exhausted; provider maintenance.
Related errors
- list models HTTP %d
- rerank HTTP %d: %s
- download generated image failed with status %d
- bazaar is offline
- get bazaar package failed, please check your network
AI-assisted analysis of siyuan-note/siyuan@251596fc0d (2026-08-12).
Data as JSON: /api/errors/a45512e5c8fa82a3.
Report an issue: GitHub.