Skip to content

Commit e7806bf

Browse files
authored
fix: Handle errors in streaming responses (#819)
Signed-off-by: Yordis Prieto <[email protected]>
1 parent e476093 commit e7806bf

File tree

2 files changed

+32
-0
lines changed

2 files changed

+32
-0
lines changed

lib/tesla/adapter/finch.ex

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,9 @@ if Code.ensure_loaded?(Finch) do
119119
{:headers, headers}, status -> send(owner, {ref, {:status, status, headers}})
120120
{:data, data}, _acc -> send(owner, {ref, {:data, data}})
121121
{:trailers, trailers}, _acc -> trailers
122+
# Handle errors passed to callback (e.g., proxy errors like {:proxy, {:unexpected_status, 403}})
123+
{:error, error}, _acc -> send(owner, {ref, {:error, error}})
124+
{:error, error, _}, _acc -> send(owner, {ref, {:error, error}})
122125
end
123126

124127
task =
@@ -139,6 +142,10 @@ if Code.ensure_loaded?(Finch) do
139142
{^ref, :eof} ->
140143
Task.await(task)
141144
nil
145+
146+
{^ref, {:error, _error}} ->
147+
Task.shutdown(task, :brutal_kill)
148+
nil
142149
after
143150
opts[:receive_timeout] ->
144151
Task.shutdown(task, :brutal_kill)
@@ -147,8 +154,13 @@ if Code.ensure_loaded?(Finch) do
147154
end)
148155

149156
{:ok, %Finch.Response{status: status, headers: headers, body: body}}
157+
158+
{^ref, {:error, error}} ->
159+
Task.shutdown(task, :brutal_kill)
160+
{:error, error}
150161
after
151162
opts[:receive_timeout] ->
163+
Task.shutdown(task, :brutal_kill)
152164
{:error, :timeout}
153165
end
154166
end

test/tesla/adapter/finch_test.exs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,4 +43,24 @@ defmodule Tesla.Adapter.FinchTest do
4343

4444
assert {:error, :timeout} = call(request, receive_timeout: 100, response: :stream)
4545
end
46+
47+
test "Stream request handles errors without raising CaseClauseError" do
48+
# This test verifies that streaming errors (like proxy 403) are properly
49+
# handled in the callback and receive blocks instead of raising CaseClauseError.
50+
# Before the fix, an error during streaming would cause:
51+
# (CaseClauseError) no case clause matching: {:error, error, nil}
52+
53+
assert {:error, _} =
54+
Tesla.Adapter.Finch.call(
55+
%Tesla.Env{
56+
method: :get,
57+
url: "http://nonexistent.invalid",
58+
body: nil,
59+
headers: []
60+
},
61+
name: @finch_name,
62+
response: :stream,
63+
receive_timeout: 1000
64+
)
65+
end
4666
end

0 commit comments

Comments
 (0)