From e65c35d63edff5eb260ad7a7a4c1ae3238788f3a Mon Sep 17 00:00:00 2001 From: drawliin Date: Thu, 30 Jul 2026 02:28:31 +0100 Subject: [PATCH 1/3] fix(ollama): close stream channel on errors --- internal/plugins/ai/ollama/ollama.go | 2 +- internal/plugins/ai/ollama/ollama_test.go | 29 +++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/internal/plugins/ai/ollama/ollama.go b/internal/plugins/ai/ollama/ollama.go index 20ef92e7..b967e735 100644 --- a/internal/plugins/ai/ollama/ollama.go +++ b/internal/plugins/ai/ollama/ollama.go @@ -106,6 +106,7 @@ func (o *Client) ListModels(_ context.Context) (ret []string, err error) { func (o *Client) SendStream(_ context.Context, msgs []*chat.ChatCompletionMessage, opts *domain.ChatOptions, channel chan domain.StreamUpdate) (err error) { ctx := context.Background() + defer close(channel) var req ollamaapi.ChatRequest if req, err = o.createChatRequest(ctx, msgs, opts); err != nil { @@ -135,7 +136,6 @@ func (o *Client) SendStream(_ context.Context, msgs []*chat.ChatCompletionMessag return } - close(channel) return } diff --git a/internal/plugins/ai/ollama/ollama_test.go b/internal/plugins/ai/ollama/ollama_test.go index 4d814db6..25dbee53 100644 --- a/internal/plugins/ai/ollama/ollama_test.go +++ b/internal/plugins/ai/ollama/ollama_test.go @@ -6,10 +6,14 @@ import ( "fmt" "net/http" "net/http/httptest" + "net/url" "strings" "testing" + "github.com/danielmiessler/fabric/internal/chat" + "github.com/danielmiessler/fabric/internal/domain" "github.com/danielmiessler/fabric/internal/i18n" + ollamaapi "github.com/ollama/ollama/api" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -60,3 +64,28 @@ func TestLoadImageBytes_DataURLSuccess(t *testing.T) { require.NoError(t, err) assert.Equal(t, expected, got) } + +func TestSendStreamClosesChannelOnChatError(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(http.StatusInternalServerError) + _, _ = w.Write([]byte(`{"error":"ollama failed"}` + "\n")) + })) + t.Cleanup(server.Close) + + baseURL, err := url.Parse(server.URL) + require.NoError(t, err) + + client := &Client{client: ollamaapi.NewClient(baseURL, server.Client())} + channel := make(chan domain.StreamUpdate) + + err = client.SendStream( + context.Background(), + []*chat.ChatCompletionMessage{{Role: chat.ChatMessageRoleUser, Content: "hello"}}, + &domain.ChatOptions{Model: "missing-model"}, + channel, + ) + + require.Error(t, err) + _, ok := <-channel + assert.False(t, ok, "stream channel should be closed when Ollama chat returns an error") +} From a4b89f65c21b5a3ab1e0473fd936b66b9ad5b096 Mon Sep 17 00:00:00 2001 From: Kayvan Sylvan Date: Sun, 2 Aug 2026 16:24:27 -0700 Subject: [PATCH 2/3] chore: incoming 2182 changelog entry --- cmd/generate_changelog/incoming/2182.txt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 cmd/generate_changelog/incoming/2182.txt diff --git a/cmd/generate_changelog/incoming/2182.txt b/cmd/generate_changelog/incoming/2182.txt new file mode 100644 index 00000000..884cf72d --- /dev/null +++ b/cmd/generate_changelog/incoming/2182.txt @@ -0,0 +1,3 @@ +### PR [#2182](https://github.com/danielmiessler/Fabric/pull/2182) by [drawliin](https://github.com/drawliin): fix(ollama): close stream channel on errors + +- Fix(ollama): close stream channel on errors From cb340b6b027f77ca21a8cc3d37d794c168e2842d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sun, 2 Aug 2026 23:32:11 +0000 Subject: [PATCH 3/3] chore(release): Update version to v1.4.468 --- CHANGELOG.md | 6 ++++++ cmd/fabric/version.go | 2 +- cmd/generate_changelog/changelog.db | Bin 4632576 -> 4636672 bytes cmd/generate_changelog/incoming/2182.txt | 3 --- nix/pkgs/fabric/version.nix | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) delete mode 100644 cmd/generate_changelog/incoming/2182.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index b8888f1b..c1c00d6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## v1.4.468 (2026-08-02) + +### PR [#2182](https://github.com/danielmiessler/Fabric/pull/2182) by [drawliin](https://github.com/drawliin): fix(ollama): close stream channel on errors + +- Fix(ollama): close stream channel on errors + ## v1.4.467 (2026-07-31) ### PR [#2171](https://github.com/danielmiessler/Fabric/pull/2171) by [OdinKral](https://github.com/OdinKral): feat(scripts): add pattern/maintenance audit script diff --git a/cmd/fabric/version.go b/cmd/fabric/version.go index 605e3cb6..1311343f 100644 --- a/cmd/fabric/version.go +++ b/cmd/fabric/version.go @@ -1,3 +1,3 @@ package main -var version = "v1.4.467" +var version = "v1.4.468" diff --git a/cmd/generate_changelog/changelog.db b/cmd/generate_changelog/changelog.db index 73c1ef0302a426253e610ffe06659c023df3d7ca..1e33fca1cf8cf680dd86fe2872c4b36e1e11a3cb 100644 GIT binary patch delta 5413 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