Skip to content

fix: re-raise DNS failures as ConnectionError in SSRF filter for universal retryability#1059

Draft
devin-ai-integration[bot] wants to merge 2 commits into
mainfrom
devin/1782293727-fix-dns-gaierror-filtered-send
Draft

fix: re-raise DNS failures as ConnectionError in SSRF filter for universal retryability#1059
devin-ai-integration[bot] wants to merge 2 commits into
mainfrom
devin/1782293727-fix-dns-gaierror-filtered-send

Conversation

@devin-ai-integration

Copy link
Copy Markdown
Contributor

Summary

The SSRF protection in filtered_send (entrypoint.py) catches socket.gaierror from _is_private_url() and re-raises it as requests.exceptions.InvalidURL. While PR #384 mapped InvalidURL → RETRY in the CDK's DEFAULT_ERROR_MAPPING, this only helps CDK HTTP streams that use the error handler. External SDKs (e.g. facebook-business in source-facebook-marketing) bypass that mapping entirely, so a transient DNS blip ([Errno -3] Temporary failure in name resolution) causes an unrecoverable sync failure instead of a retry.

Fix: Re-raise socket.gaierror as requests.ConnectionError instead of InvalidURL. ConnectionError is universally retried by both CDK streams and external SDK error handlers.

 except socket.gaierror as exception:
-    raise requests.exceptions.InvalidURL(f"Invalid URL {parsed_url}: {exception}")
+    hostname = parsed_url.hostname or ""
+    raise requests.ConnectionError(
+        f"DNS resolution failed for {str(hostname)}: {str(exception)}"
+    )

The error message is also improved: "DNS resolution failed for graph.facebook.com: ..." instead of the misleading "Invalid URL ParseResult(...): ...".

Resolves https://github.com/airbytehq/oncall/issues/12976:

Prior art:

Breaking Change Evaluation

Not breaking. This change makes error handling more lenient (retryable instead of fatal) without changing any connector spec, schema, state format, or stream definition. No version bump artifacts needed — CDK uses dynamic versioning.

Test Coverage

Added parametrized tests in unit_tests/test_entrypoint.py covering the filtered_send code path directly:

  • test_filtered_send_raises_connection_error_on_dns_failure — parametrized with EAI_AGAIN, EAI_NONAME, EAI_FAIL errno values
  • test_filtered_send_does_not_raise_invalid_url_on_dns_failure — verifies old behavior (InvalidURL) no longer occurs
  • Updated existing test_cloud_incorrect_ip_format_is_rejected to expect ConnectionError

Link to Devin session: https://app.devin.ai/sessions/ad69979101834fc8a9d3b334b1d131f9

…iversal retryability

The SSRF protection in filtered_send caught socket.gaierror from
_is_private_url and re-raised it as requests.exceptions.InvalidURL.
While CDK streams handle InvalidURL as retryable (via PR #384), external
SDKs (e.g. facebook-business) do not, causing transient DNS blips to
produce unrecoverable sync failures.

Change the exception type to requests.ConnectionError, which is
universally retried by both CDK streams and external SDK error
handlers.

Co-Authored-By: bot_apk <apk@cognition.ai>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@github-actions

Copy link
Copy Markdown

👋 Greetings, Airbyte Team Member!

Here are some helpful tips and reminders for your convenience.

💡 Show Tips and Tricks

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@devin/1782293727-fix-dns-gaierror-filtered-send#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 devin/1782293727-fix-dns-gaierror-filtered-send

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
  • /prerelease - Triggers a prerelease publish with default arguments
  • /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
📚 Show Repo Guidance

Helpful Resources

📝 Edit this welcome message.

@github-actions

github-actions Bot commented Jun 24, 2026

Copy link
Copy Markdown

PyTest Results (Fast)

916 tests   - 3 203   905 ✅  - 3 203   10m 57s ⏱️ + 2m 41s
  1 suites ±    0    10 💤  -     1 
  1 files   ±    0     1 ❌ +    1 

For more details on these failures, see this check.

Results for commit 701f38b. ± Comparison against base commit 977f051.

This pull request removes 3207 and adds 4 tests. Note that renamed tests count towards both.
unit_tests.sources.declarative.decoders.test_composite_decoder ‑ test_given_response_already_consumed_when_decode_then_no_data_is_returned
unit_tests.sources.declarative.decoders.test_composite_decoder ‑ test_given_response_is_not_streamed_when_decode_then_can_be_called_multiple_times
unit_tests.sources.declarative.decoders.test_composite_decoder ‑ test_json_items_parser_composes_with_gzip
unit_tests.sources.declarative.decoders.test_composite_decoder ‑ test_json_items_parser_honors_encoding[iso-8859-1]
unit_tests.sources.declarative.decoders.test_composite_decoder ‑ test_json_items_parser_honors_encoding[utf-8]
unit_tests.sources.declarative.decoders.test_composite_decoder ‑ test_json_items_parser_is_lazy
unit_tests.sources.declarative.decoders.test_composite_decoder ‑ test_json_items_parser_requires_items_path
unit_tests.sources.declarative.decoders.test_composite_decoder ‑ test_json_items_parser_yields_each_item[empty_array]
unit_tests.sources.declarative.decoders.test_composite_decoder ‑ test_json_items_parser_yields_each_item[nested_array]
unit_tests.sources.declarative.decoders.test_composite_decoder ‑ test_json_items_parser_yields_each_item[top_level_array]
…
unit_tests.test_entrypoint ‑ test_filtered_send_dns_failure_is_not_invalid_url
unit_tests.test_entrypoint ‑ test_filtered_send_raises_connection_error_on_dns_failure[permanent_dns_EAI_FAIL]
unit_tests.test_entrypoint ‑ test_filtered_send_raises_connection_error_on_dns_failure[transient_dns_EAI_AGAIN]
unit_tests.test_entrypoint ‑ test_filtered_send_raises_connection_error_on_dns_failure[unknown_host_EAI_NONAME]

♻️ This comment has been updated with latest results.

Comment thread unit_tests/test_entrypoint.py Fixed
Update connector_builder tests that checked for 'Invalid URL' in
stacktraces to expect 'DNS resolution failed for domainwithoutextension'
instead. Also clean up empty except clause in test per bot feedback.

Co-Authored-By: bot_apk <apk@cognition.ai>
@github-actions

Copy link
Copy Markdown

PyTest Results (Full)

4 126 tests  +4   4 113 ✅ +3   17m 0s ⏱️ + 5m 24s
    1 suites ±0      12 💤 ±0 
    1 files   ±0       1 ❌ +1 

For more details on these failures, see this check.

Results for commit 701f38b. ± Comparison against base commit 977f051.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants