Skip to content

Commit e69e1f0

Browse files
-- introduce ClientError as a shared superclass for all 4xx errors
-- Previously, AuthenticationError, InvalidRequestError, and NotFoundError all inherited directly from the base Error class, making it impossible to rescue "any client error" without listing them individually. -- This adds ClientError as a middle tier so callers can choose their rescue granularity — catch a specific 4xx, catch all 4xx, or catch everything without breaking any existing rescue clauses. Closes #1 (partial — request_id and JobFailedError deferred, see issue)
1 parent 6f4dcc6 commit e69e1f0

3 files changed

Lines changed: 48 additions & 4 deletions

File tree

lib/crewai/errors.rb

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
module CrewAI
44
class Error < StandardError; end
55

6-
class AuthenticationError < Error; end
6+
class ClientError < Error; end
77

8-
class InvalidRequestError < Error; end
8+
class AuthenticationError < ClientError; end
99

10-
class NotFoundError < Error; end
10+
class InvalidRequestError < ClientError; end
11+
12+
class NotFoundError < ClientError; end
1113

1214
class ServerError < Error; end
1315

ruby-crewai.gemspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ Gem::Specification.new do |spec|
99
spec.email = ["78165374+MuhammadIbtisam@users.noreply.github.com"]
1010

1111
spec.summary = "Ruby client for the CrewAI AMP HTTP API"
12-
spec.description = "A minimal, production-grade Ruby client for CrewAI AMP REST endpoints: inputs, kickoff, status, and resume."
12+
spec.description = "A minimal, production-grade Ruby client for CrewAI AMP REST endpoints: healthcheck, inputs, kickoff, status, and resume."
1313
spec.homepage = "https://github.com/MuhammadIbtisam/ruby-crewai"
1414
spec.license = "MIT"
1515

spec/crewai/client/error_handling_spec.rb

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,37 @@
1010
let(:client) { described_class.new(configuration: configuration) }
1111
let(:uri_base) { "https://test.crewai.com" }
1212

13+
describe "4xx errors are rescuable as CrewAI::ClientError" do
14+
{
15+
"401" => [401, "Unauthorized", CrewAI::AuthenticationError],
16+
"422" => [422, "Bad input", CrewAI::InvalidRequestError],
17+
"404" => [404, "Not found", CrewAI::NotFoundError]
18+
}.each do |label, (status, message, klass)|
19+
context "when the server returns #{label} (#{klass})" do
20+
before do
21+
stub_request(:get, "#{uri_base}/healthcheck")
22+
.to_return(
23+
status: status,
24+
body: { "message" => message }.to_json,
25+
headers: { "Content-Type" => "application/json" }
26+
)
27+
end
28+
29+
it "raises #{klass}" do
30+
expect { client.healthcheck }.to raise_error(klass)
31+
end
32+
33+
it "is rescuable as CrewAI::ClientError" do
34+
expect { client.healthcheck }.to raise_error(CrewAI::ClientError)
35+
end
36+
37+
it "is rescuable as CrewAI::Error" do
38+
expect { client.healthcheck }.to raise_error(CrewAI::Error)
39+
end
40+
end
41+
end
42+
end
43+
1344
describe "transport errors" do
1445
context "when the request times out" do
1546
before do
@@ -32,6 +63,17 @@
3263
expect { client.healthcheck }.to raise_error(CrewAI::ConnectionError, /connection refused/)
3364
end
3465
end
66+
67+
context "when an SSL error occurs" do
68+
before do
69+
stub_request(:get, "#{uri_base}/healthcheck")
70+
.to_raise(Faraday::SSLError.new("SSL certificate verify failed"))
71+
end
72+
73+
it "raises CrewAI::ConnectionError" do
74+
expect { client.healthcheck }.to raise_error(CrewAI::ConnectionError, /SSL certificate verify failed/)
75+
end
76+
end
3577
end
3678

3779
describe "unexpected HTTP status (catch-all)" do

0 commit comments

Comments
 (0)