Skip to content

Conversation

@maxi297
Copy link
Contributor

@maxi297 maxi297 commented Oct 14, 2025

Summary by CodeRabbit

  • Bug Fixes

    • Corrected a spelling inconsistency in variable names related to response filters.
  • Refactor

    • Modified error handling so that default HttpResponseFilters are not automatically added; only explicitly provided filters are used.
    • Updated various error handler methods to allow for absent (None) error resolutions instead of constructing default messages.
    • Streamlined how HTTP error resolutions are handled, ensuring a clear distinction between success and error outcomes.
  • Tests

    • Simplified test cases to reflect updated error resolution handling.

@github-actions
Copy link

👋 Greetings, Airbyte Team Member!

Here are some helpful tips and reminders for your convenience.

Testing This CDK Version

You can test this version of the CDK using the following:

# Run the CLI from this branch:
uvx 'git+https://github.com/airbytehq/airbyte-python-cdk.git@maxi297/poc_error_handler_change#egg=airbyte-python-cdk[dev]' --help

# Update a connector to use the CDK from this branch ref:
cd airbyte-integrations/connectors/source-example
poe use-cdk-branch maxi297/poc_error_handler_change

Helpful Resources

PR Slash Commands

Airbyte Maintainers can execute the following slash commands on your PR:

  • /autofix - Fixes most formatting and linting issues
  • /poetry-lock - Updates poetry.lock file
  • /test - Runs connector tests with the updated CDK
  • /poe build - Regenerate git-committed build artifacts, such as the pydantic models which are generated from the manifest JSON schema in YAML.
  • /poe <command> - Runs any poe command in the CDK environment

📝 Edit this welcome message.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 14, 2025

📝 Walkthrough

Walkthrough

The error-handling API now allows interpret_response to return Optional[ErrorResolution] across interfaces and implementations. Fallback error resolution creation was removed (now returns None). HTTP client defaults None to a SUCCESS resolution. A default HttpResponseFilter is no longer auto-added in the declarative factory. A variable name typo was corrected.

Changes

Cohort / File(s) Summary
Error handler API and implementations
airbyte_cdk/sources/streams/http/error_handlers/error_handler.py, .../http_status_error_handler.py, .../response_models.py
interpret_response return type changed to Optional[ErrorResolution]; HttpStatusErrorHandler signature updated; create_fallback_error_resolution now returns None instead of constructing a fallback ErrorResolution.
Composite error handling (declarative)
airbyte_cdk/sources/declarative/requesters/error_handlers/composite_error_handler.py
interpret_response now returns Optional[ErrorResolution]; loop only returns when an ErrorResolution is produced; fallback matched result logic removed.
HTTP request flow
airbyte_cdk/sources/streams/http/http.py, .../http_client.py
Propagated Optional[ErrorResolution] return from interpret_response; _send now defaults None to SUCCESS before handling, ensuring a non-None resolution is passed to _handle_error_resolution.
Declarative factory defaults
airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py
Removed automatic appending of default HttpResponseFilter in create_default_error_handler; behavior relies solely on model-provided response_filters.
Naming cleanup
airbyte_cdk/sources/declarative/requesters/error_handlers/default_error_handler.py
Renamed variable from default_reponse_filter to default_response_filter; no logic change.
Tests
unit_tests/sources/streams/http/error_handlers/test_response_models.py
Updated tests: create_fallback_error_resolution expected to return None; removed prior message/status-based assertions; added Mock import.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant C as HttpClient
  participant H as ErrorHandler
  participant S as Server

  C->>S: Send HTTP request
  S-->>C: Response / Exception
  C->>H: interpret_response(response_or_exception)
  H-->>C: Optional ErrorResolution (may be None)
  alt Resolution is None
    Note over C: Default to SUCCESS resolution
  else Resolution provided
    Note over C: Use provided resolution
  end
  C->>C: _handle_error_resolution(resolution)
Loading
sequenceDiagram
  autonumber
  participant CEH as CompositeErrorHandler
  participant EH1 as ErrorHandler A
  participant EH2 as ErrorHandler B

  CEH->>EH1: interpret_response(ctx)
  EH1-->>CEH: Optional ErrorResolution
  alt EH1 returned ErrorResolution
    CEH-->>CEH: Return that resolution
  else EH1 returned None
    CEH->>EH2: interpret_response(ctx)
    EH2-->>CEH: Optional ErrorResolution
    alt EH2 returned ErrorResolution
      CEH-->>CEH: Return that resolution
    else No handlers matched
      Note over CEH: No fallback resolution (returns None)
    end
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Suggested labels

chore

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title succinctly captures the key change—allowing ErrorHandler.interpret_response to return None—which directly reflects the main modification to the error‐handling API in this changeset.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch maxi297/poc_error_handler_change

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
airbyte_cdk/sources/declarative/requesters/error_handlers/default_error_handler.py (1)

111-132: Adjust interpret_response contract to Optional

Now that create_fallback_error_resolution returns None, this override can leak None even though its signature still promises an ErrorResolution, which breaks the new abstract signature and trips our type checks. Could we update the return annotation to Optional[ErrorResolution] (and let callers keep handling the None case) to stay aligned, wdyt?

-    def interpret_response(
-        self, response_or_exception: Optional[Union[requests.Response, Exception]]
-    ) -> ErrorResolution:
+    def interpret_response(
+        self, response_or_exception: Optional[Union[requests.Response, Exception]]
+    ) -> Optional[ErrorResolution]:
airbyte_cdk/sources/streams/http/http_client.py (1)

345-385: Let ruff format this new expression

The formatter is currently failing on this file, and the new ternary line is the culprit. Could we run poetry run ruff format . (or wrap this assignment manually) so the pipeline goes green, wdyt?

🧹 Nitpick comments (2)
airbyte_cdk/sources/declarative/requesters/error_handlers/composite_error_handler.py (1)

59-68: Acknowledge expected pipeline failures.

The pipeline failures at line 68 are expected as part of this PR's design:

[error] 68-68: "create_fallback_error_resolution" does not return a value (it only ever returns None)

According to the AI summary, create_fallback_error_resolution now returns None instead of creating a fallback resolution, and the HTTP client is responsible for substituting a default SUCCESS resolution when it receives None. The logic change at line 65 (checking isinstance) correctly ensures only concrete ErrorResolution instances are returned early, allowing the fallback to None at line 68 when no handler matches.

Based on the PR design, wdyt about adding a comment at line 68 explaining that None is intentional and handled by the HTTP client? This would help future maintainers understand the contract.

+        # Return None when no handler matches; HTTP client will substitute a default SUCCESS resolution
         return create_fallback_error_resolution(response_or_exception)
airbyte_cdk/sources/streams/http/http.py (1)

629-633: Guard against None from super().interpret_response?

Since super().interpret_response() now returns Optional[ErrorResolution], it may return None here—should we fallback to a default ErrorResolution for consistency, or rely on callers to handle None? wdyt?

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 035264c and b6dd0fa.

📒 Files selected for processing (9)
  • airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py (0 hunks)
  • airbyte_cdk/sources/declarative/requesters/error_handlers/composite_error_handler.py (1 hunks)
  • airbyte_cdk/sources/declarative/requesters/error_handlers/default_error_handler.py (1 hunks)
  • airbyte_cdk/sources/streams/http/error_handlers/error_handler.py (1 hunks)
  • airbyte_cdk/sources/streams/http/error_handlers/http_status_error_handler.py (1 hunks)
  • airbyte_cdk/sources/streams/http/error_handlers/response_models.py (1 hunks)
  • airbyte_cdk/sources/streams/http/http.py (1 hunks)
  • airbyte_cdk/sources/streams/http/http_client.py (2 hunks)
  • unit_tests/sources/streams/http/error_handlers/test_response_models.py (2 hunks)
💤 Files with no reviewable changes (1)
  • airbyte_cdk/sources/declarative/parsers/model_to_component_factory.py
🧰 Additional context used
🧬 Code graph analysis (7)
airbyte_cdk/sources/declarative/requesters/error_handlers/default_error_handler.py (2)
airbyte_cdk/sources/declarative/requesters/error_handlers/default_http_response_filter.py (2)
  • DefaultHttpResponseFilter (21-40)
  • matches (22-40)
airbyte_cdk/sources/declarative/requesters/error_handlers/http_response_filter.py (1)
  • matches (72-118)
airbyte_cdk/sources/streams/http/http_client.py (6)
airbyte_cdk/sources/streams/http/error_handlers/response_models.py (2)
  • ErrorResolution (24-27)
  • ResponseAction (14-20)
airbyte_cdk/sources/declarative/requesters/error_handlers/composite_error_handler.py (1)
  • interpret_response (59-68)
airbyte_cdk/sources/declarative/requesters/error_handlers/default_error_handler.py (1)
  • interpret_response (111-132)
airbyte_cdk/sources/streams/http/error_handlers/error_handler.py (1)
  • interpret_response (33-42)
airbyte_cdk/sources/streams/http/error_handlers/http_status_error_handler.py (1)
  • interpret_response (48-110)
airbyte_cdk/sources/streams/http/http.py (1)
  • interpret_response (629-673)
airbyte_cdk/sources/declarative/requesters/error_handlers/composite_error_handler.py (5)
airbyte_cdk/sources/streams/http/error_handlers/response_models.py (1)
  • ErrorResolution (24-27)
airbyte_cdk/sources/declarative/requesters/error_handlers/default_error_handler.py (1)
  • interpret_response (111-132)
airbyte_cdk/sources/streams/http/error_handlers/error_handler.py (1)
  • interpret_response (33-42)
airbyte_cdk/sources/streams/http/error_handlers/http_status_error_handler.py (1)
  • interpret_response (48-110)
airbyte_cdk/sources/streams/http/http.py (1)
  • interpret_response (629-673)
airbyte_cdk/sources/streams/http/http.py (1)
airbyte_cdk/sources/streams/http/error_handlers/response_models.py (1)
  • ErrorResolution (24-27)
airbyte_cdk/sources/streams/http/error_handlers/http_status_error_handler.py (1)
airbyte_cdk/sources/streams/http/error_handlers/response_models.py (1)
  • ErrorResolution (24-27)
airbyte_cdk/sources/streams/http/error_handlers/error_handler.py (1)
airbyte_cdk/sources/streams/http/error_handlers/response_models.py (1)
  • ErrorResolution (24-27)
unit_tests/sources/streams/http/error_handlers/test_response_models.py (1)
airbyte_cdk/sources/streams/http/error_handlers/response_models.py (1)
  • create_fallback_error_resolution (46-49)
🪛 GitHub Actions: Linters
airbyte_cdk/sources/declarative/requesters/error_handlers/default_error_handler.py

[error] 131-131: "create_fallback_error_resolution" does not return a value (it only ever returns None) [func-returns-value]

airbyte_cdk/sources/streams/http/http_client.py

[error] 380-380: Ruff formatting check failed. 1 file would be reformatted by 'poetry run ruff format --diff .'

airbyte_cdk/sources/declarative/requesters/error_handlers/composite_error_handler.py

[error] 68-68: Returning Any from function declared to return "ErrorResolution | None" [no-any-return]


[error] 68-68: "create_fallback_error_resolution" does not return a value (it only ever returns None) [func-returns-value]

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (12)
  • GitHub Check: Check: source-hardcoded-records
  • GitHub Check: Check: source-shopify
  • GitHub Check: Check: destination-motherduck
  • GitHub Check: Check: source-pokeapi
  • GitHub Check: Check: source-intercom
  • GitHub Check: Pytest (All, Python 3.13, Ubuntu)
  • GitHub Check: Pytest (All, Python 3.11, Ubuntu)
  • GitHub Check: Pytest (All, Python 3.12, Ubuntu)
  • GitHub Check: Pytest (All, Python 3.10, Ubuntu)
  • GitHub Check: Pytest (Fast)
  • GitHub Check: SDM Docker Image Build
  • GitHub Check: Manifest Server Docker Image Build
🔇 Additional comments (1)
airbyte_cdk/sources/streams/http/error_handlers/http_status_error_handler.py (1)

48-50: LGTM! Signature aligns with interface.

The return type change to Optional[ErrorResolution] maintains consistency with the updated ErrorHandler interface. While this implementation always returns a concrete ErrorResolution, the optional return type provides flexibility for other implementations and maintains a uniform contract.

@github-actions
Copy link

PyTest Results (Fast)

1 473 tests   - 2 324   1 461 ✅  - 2 324   5m 22s ⏱️ - 1m 10s
    1 suites ±    0      11 💤  -     1 
    1 files   ±    0       1 ❌ +    1 

For more details on these failures, see this check.

Results for commit b6dd0fa. ± Comparison against base commit 035264c.

This pull request removes 2324 tests.
unit_tests.sources.declarative.requesters.error_handlers.backoff_strategies.test_constant_backoff ‑ test_constant_backoff[test_constant_backoff_attempt_round_float-1.0-6.7-6.7]
unit_tests.sources.declarative.requesters.error_handlers.backoff_strategies.test_constant_backoff ‑ test_constant_backoff[test_constant_backoff_attempt_round_float-1.5-6.7-6.7]
unit_tests.sources.declarative.requesters.error_handlers.backoff_strategies.test_constant_backoff ‑ test_constant_backoff[test_constant_backoff_first_attempt-1-10-10]
unit_tests.sources.declarative.requesters.error_handlers.backoff_strategies.test_constant_backoff ‑ test_constant_backoff[test_constant_backoff_first_attempt_float-1-6.7-6.7]
unit_tests.sources.declarative.requesters.error_handlers.backoff_strategies.test_constant_backoff ‑ test_constant_backoff[test_constant_backoff_first_attempt_round_float-1-10.0-10]
unit_tests.sources.declarative.requesters.error_handlers.backoff_strategies.test_constant_backoff ‑ test_constant_backoff[test_constant_backoff_from_config-1-{{ config['backoff'] }}-30]
unit_tests.sources.declarative.requesters.error_handlers.backoff_strategies.test_constant_backoff ‑ test_constant_backoff[test_constant_backoff_from_parameters-1-{{ parameters['backoff'] }}-20]
unit_tests.sources.declarative.requesters.error_handlers.backoff_strategies.test_constant_backoff ‑ test_constant_backoff[test_constant_backoff_second_attempt_round_float-2-10.0-10]
unit_tests.sources.declarative.requesters.error_handlers.backoff_strategies.test_exponential_backoff ‑ test_exponential_backoff[test_exponential_backoff_first_attempt-1-5-10]
unit_tests.sources.declarative.requesters.error_handlers.backoff_strategies.test_exponential_backoff ‑ test_exponential_backoff[test_exponential_backoff_from_config-2-{{config['backoff']}}-20]
…

@github-actions
Copy link

PyTest Results (Full)

3 797 tests   - 3   3 780 ✅  - 8   11m 7s ⏱️ +8s
    1 suites ±0      12 💤 ±0 
    1 files   ±0       5 ❌ +5 

For more details on these failures, see this check.

Results for commit b6dd0fa. ± Comparison against base commit 035264c.

This pull request removes 3 tests.
unit_tests.sources.streams.http.error_handlers.test_response_models.DefaultErrorResolutionTest ‑ test_given_exception_when_create_fallback_error_resolution_then_return_error_resolution
unit_tests.sources.streams.http.error_handlers.test_response_models.DefaultErrorResolutionTest ‑ test_given_response_can_raise_for_status_when_create_fallback_error_resolution_then_error_resolution
unit_tests.sources.streams.http.error_handlers.test_response_models.DefaultErrorResolutionTest ‑ test_given_response_is_ok_when_create_fallback_error_resolution_then_error_resolution

)
response_filters.append(
HttpResponseFilter(config=config, parameters=model.parameters or {})
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why was this needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume because the fallback is create_fallback_error_resolution which was returning a system_error with RETRY

@brianjlai
Copy link
Contributor

pending fixing tests obv

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants