Skip to content

Commit 6ba781e

Browse files
authored
Reply cleanly on unhandled credential errors in run channel (#4881)
RunChannel.handle_credential_error/5 pattern-matched a fixed set of error tags with no fallback, so an unexpected error term — most notably an OAuth provider timeout during token refresh, which surfaces as an untyped transport error — raised FunctionClauseError and crashed the channel mid-fetch:credential, dropping the worker's connection. Add a fallback clause that logs the unexpected term and replies with a clean error so the worker receives a response instead of losing the connection.
1 parent 12d09be commit 6ba781e

4 files changed

Lines changed: 41 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ and this project adheres to
4242

4343
### Fixed
4444

45+
- Stop the run channel from crashing during `fetch:credential` when an OAuth
46+
provider times out while refreshing a token.
47+
[#4853](https://github.com/OpenFn/lightning/issues/4853)
4548
- Stop the collaborative editor's Session (and the Phoenix channel calling it)
4649
from crashing when the cross-node `SharedDoc.unobserve/1` during cleanup hits
4750
a SharedDoc on a node that is unreachable (`:noconnection`) or slow to reply

lib/lightning/credentials/resolver.ex

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ defmodule Lightning.Credentials.Resolver do
5555
| :project_not_found
5656
| :environment_mismatch
5757
| Credentials.oauth_refresh_error()
58+
| term()
5859

5960
@type resolve_error :: {error_reason(), Credential.t() | nil}
6061

lib/lightning_web/channels/run_channel.ex

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,4 +549,15 @@ defmodule LightningWeb.RunChannel do
549549
{:reply, {:error, "Could not reach the OAuth provider. Try again later"},
550550
socket}
551551
end
552+
553+
# Fallback for unexpected error terms
554+
defp handle_credential_error(socket, error, id, _project_id, run_id) do
555+
Logger.warning(
556+
"Unhandled credential resolution error for credential #{id} " <>
557+
"(run #{run_id}): #{inspect(error)}"
558+
)
559+
560+
{:reply, {:error, "Could not reach the OAuth provider. Try again later"},
561+
socket}
562+
end
552563
end

test/lightning_web/channels/run_channel_test.exs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,32 @@ defmodule LightningWeb.RunChannelTest do
656656
:error,
657657
"Could not reach the OAuth provider. Try again later"
658658
end
659+
660+
@tag capture_log: true
661+
test "replies cleanly when the OAuth provider times out", %{
662+
credential: credential,
663+
user: user
664+
} do
665+
credential = Repo.preload(credential, :oauth_client)
666+
endpoint = credential.oauth_client.token_endpoint
667+
668+
Lightning.AuthProviders.OauthHTTPClient.Mock
669+
|> Mox.expect(:call, fn
670+
%Tesla.Env{method: :post, url: ^endpoint}, _opts ->
671+
{:error, :timeout}
672+
end)
673+
674+
%{socket: socket} =
675+
create_socket_and_run(%{credential: credential, user: user})
676+
677+
ref = push(socket, "fetch:credential", %{"id" => credential.id})
678+
679+
# The timeout is an untyped transport error; the channel must reply with
680+
# an error rather than crashing with a FunctionClauseError.
681+
assert_reply ref,
682+
:error,
683+
"Could not reach the OAuth provider. Try again later"
684+
end
659685
end
660686

661687
describe "marking steps as started and finished" do

0 commit comments

Comments
 (0)