server/internal/registry: make pull send errors with Error field (#10326)

Previously, the pull handler would send an error message in the Status
field, this prevented the client from using the message as a signal to
stop. In the case of the "run" command, it would follow the pull with a
"show" which would print a nearly identical "not found" message for
unresolved models.

Fixes #10307
This commit is contained in:
Blake Mizerany 2025-04-18 18:12:28 -07:00 committed by GitHub
parent 40b8fdbdca
commit 4e535e6188
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 9 additions and 7 deletions

View File

@ -244,6 +244,7 @@ func (s *Local) handleDelete(_ http.ResponseWriter, r *http.Request) error {
} }
type progressUpdateJSON struct { type progressUpdateJSON struct {
Error string `json:"error,omitempty,omitzero"`
Status string `json:"status,omitempty,omitzero"` Status string `json:"status,omitempty,omitzero"`
Digest blob.Digest `json:"digest,omitempty,omitzero"` Digest blob.Digest `json:"digest,omitempty,omitzero"`
Total int64 `json:"total,omitempty,omitzero"` Total int64 `json:"total,omitempty,omitzero"`
@ -348,14 +349,15 @@ func (s *Local) handlePull(w http.ResponseWriter, r *http.Request) error {
case err := <-done: case err := <-done:
flushProgress() flushProgress()
if err != nil { if err != nil {
var status string
if errors.Is(err, ollama.ErrModelNotFound) { if errors.Is(err, ollama.ErrModelNotFound) {
status = fmt.Sprintf("error: model %q not found", p.model()) return &serverError{
Status: 404,
Code: "not_found",
Message: fmt.Sprintf("model %q not found", p.model()),
}
} else { } else {
status = fmt.Sprintf("error: %v", err) return err
} }
enc.Encode(progressUpdateJSON{Status: status})
return nil
} }
// Emulate old client pull progress (for now): // Emulate old client pull progress (for now):

View File

@ -221,7 +221,7 @@ func TestServerPull(t *testing.T) {
got = s.send(t, "POST", "/api/pull", `{"model": "unknown"}`) got = s.send(t, "POST", "/api/pull", `{"model": "unknown"}`)
checkResponse(got, ` checkResponse(got, `
{"status":"error: model \"unknown\" not found"} {"code":"not_found","error":"model \"unknown\" not found"}
`) `)
got = s.send(t, "DELETE", "/api/pull", `{"model": "smol"}`) got = s.send(t, "DELETE", "/api/pull", `{"model": "smol"}`)
@ -235,7 +235,7 @@ func TestServerPull(t *testing.T) {
got = s.send(t, "POST", "/api/pull", `{"model": "://"}`) got = s.send(t, "POST", "/api/pull", `{"model": "://"}`)
checkResponse(got, ` checkResponse(got, `
{"status":"error: invalid or missing name: \"\""} {"code":"bad_request","error":"invalid or missing name: \"\""}
`) `)
// Non-streaming pulls // Non-streaming pulls