Skip to content

fix: route RequestBodyPlainText to request_body_data instead of request_body_json#971

Open
Airbyte Support (Airbyte-Support) wants to merge 3 commits intomainfrom
devin/1775019092-fix-request-body-plain-text
Open

fix: route RequestBodyPlainText to request_body_data instead of request_body_json#971
Airbyte Support (Airbyte-Support) wants to merge 3 commits intomainfrom
devin/1775019092-fix-request-body-plain-text

Conversation

@Airbyte-Support
Copy link
Copy Markdown

@Airbyte-Support Airbyte Support (Airbyte-Support) commented Apr 1, 2026

Summary

RequestBodyPlainText was incorrectly grouped with RequestBodyJsonObject in InterpolatedRequestOptionsProvider._resolve_request_body(), causing plain text body values to be assigned to request_body_json instead of request_body_data. This resulted in a ValueError("Request body json cannot be a string") whenever a user configured a plain-text request body in the Connector Builder — for example, when creating an asynchronous job with a non-JSON body.

The fix splits the combined elif branch so that RequestBodyPlainText routes to self.request_body_data (like RequestBodyUrlEncodedForm already does), while RequestBodyJsonObject continues to route to self.request_body_json.

Migration backward compatibility

The manifest migration (HttpRequesterRequestBodyJsonDataToRequestBody) previously converted string-valued request_body_json fields to RequestBodyPlainText. Before this fix, that worked by accident because RequestBodyPlainText was (incorrectly) routed to request_body_json. Now that RequestBodyPlainText correctly routes to request_body_data, the migration would break existing connectors that rely on string JSON templates being sent as JSON bodies.

The fix: string-valued request_body_json fields are now skipped by the migration and left as request_body_json, where InterpolatedNestedRequestInputProvider already handles them natively (interpolating the template string and parsing it via ast.literal_eval into a dict).

Changes to the migration:

  • should_migrate returns False when the only migratable key is a string request_body_json
  • _migrate_body_json returns early (no-op) for string values instead of converting to RequestBodyPlainText
  • validate accepts manifests where string request_body_json remains unmigrated
  • Removed unused text_type variable

Review & Testing Checklist for Human

  • End-to-end in Connector Builder: Configure an async job creation request with a plain-text request body and confirm the request is sent correctly without the "Request body json cannot be a string" error. This is the primary user-facing scenario.
  • Existing connectors: Confirm that connectors currently using string-valued request_body_json (e.g., '{"nested": {"key": "{{ config.option }}"}}') continue to send JSON bodies after this change, not raw string data.
  • Migration edge cases: Verify that a manifest with both a string request_body_json and a request_body_data key migrates correctly — request_body_data should be migrated to RequestBodyUrlEncodedForm while the string request_body_json is left in place.
  • Known limitation — ast.literal_eval in interpolation layer: JinjaInterpolation applies ast.literal_eval to rendered string values. This means a plain-text body whose content looks like a Python literal (e.g., {"a": 1} or 5) could be parsed into a dict/int rather than staying a string. This is pre-existing behavior that affects all string-valued request_body_data paths (including RequestBodyUrlEncodedForm) and is not introduced by this PR, but it is worth being aware of for plain-text bodies. A follow-up PR could address this in the interpolation layer if needed.

Notes

  • The old test "test_string" in test_interpolated_request_json_using_request_body was encoding the buggy behavior: it expected RequestBodyPlainText with value '{"nested": { "key": "..." }}' to produce a parsed JSON dict. This test has been removed and replaced with two new cases in test_interpolated_request_data_using_request_body.
  • The migration test fixtures in conftest.py have been updated so the expected output for stream "D" (string request_body_json) retains the original request_body_json key rather than converting to RequestBodyPlainText.
  • Verified locally by Alfredo Garcia (@agarctfi) (comment).
  • Related oncall issue: airbytehq/oncall#10360

Link to Devin session: https://app.devin.ai/sessions/8a5ed7c6c890468ca63a35469e5c58c1
Requested by: Airbyte Support (@Airbyte-Support)

Summary by CodeRabbit

  • Bug Fixes
    • Fixed request-body migration to avoid converting string-encoded JSON into a structured body and to correctly distinguish plain-text from JSON request bodies.
  • Tests
    • Updated and expanded tests to validate plain-text request bodies and interpolation, and removed cases that treated plain-text as parsed JSON.

…st_body_json

Co-Authored-By: syed.khadeer@airbyte.io <cloud-support@airbyte.io>
@devin-ai-integration
Copy link
Copy Markdown
Contributor

🤖 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 and CI monitoring

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 1, 2026

👋 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/1775019092-fix-request-body-plain-text#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/1775019092-fix-request-body-plain-text

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.

@syedkhadeer-cmd syedkhadeer-cmd self-assigned this Apr 1, 2026
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 1, 2026

PyTest Results (Fast)

4 013 tests  +38   4 002 ✅ +38   7m 49s ⏱️ +17s
    1 suites ± 0      11 💤 ± 0 
    1 files   ± 0       0 ❌ ± 0 

Results for commit 77399c2. ± Comparison against base commit 69cd63d.

This pull request removes 8 and adds 46 tests. Note that renamed tests count towards both.
unit_tests.sources.declarative.requesters.request_options.test_interpolated_request_options_provider ‑ test_interpolated_request_json_using_request_body[test_graphql_query-input_request_json13-expected_request_json13]
unit_tests.sources.declarative.requesters.request_options.test_interpolated_request_options_provider ‑ test_interpolated_request_json_using_request_body[test_nested_objects-input_request_json11-expected_request_json11]
unit_tests.sources.declarative.requesters.request_options.test_interpolated_request_options_provider ‑ test_interpolated_request_json_using_request_body[test_nested_objects_interpolated keys-input_request_json12-expected_request_json12]
unit_tests.sources.declarative.requesters.request_options.test_interpolated_request_options_provider ‑ test_interpolated_request_json_using_request_body[test_string-input_request_json10-expected_request_json10]
unit_tests.utils.test_memory_monitor ‑ test_cgroup_v1_emits_warning
unit_tests.utils.test_memory_monitor ‑ test_logs_at_90_percent
unit_tests.utils.test_memory_monitor ‑ test_logs_on_every_check_above_90_percent
unit_tests.utils.test_memory_monitor ‑ test_no_warning_below_threshold
unit_tests.sources.declarative.extractors.test_dpath_extractor ‑ test_dpath_extractor_expands_non_mapping_safely
unit_tests.sources.declarative.extractors.test_dpath_extractor ‑ test_dpath_extractor_interpolated_expand_path
unit_tests.sources.declarative.extractors.test_dpath_extractor ‑ test_dpath_extractor_non_dict_items_with_parent_context
unit_tests.sources.declarative.extractors.test_dpath_extractor ‑ test_dpath_extractor_on_no_records[on_no_records_emit_parent_empty_array]
unit_tests.sources.declarative.extractors.test_dpath_extractor ‑ test_dpath_extractor_on_no_records[on_no_records_emit_parent_has_items_extracts_normally]
unit_tests.sources.declarative.extractors.test_dpath_extractor ‑ test_dpath_extractor_on_no_records[on_no_records_emit_parent_missing_path]
unit_tests.sources.declarative.extractors.test_dpath_extractor ‑ test_dpath_extractor_on_no_records[on_no_records_emit_parent_non_array]
unit_tests.sources.declarative.extractors.test_dpath_extractor ‑ test_dpath_extractor_on_no_records[on_no_records_skip_empty_array]
unit_tests.sources.declarative.extractors.test_dpath_extractor ‑ test_dpath_extractor_on_no_records[on_no_records_skip_missing_path]
unit_tests.sources.declarative.extractors.test_dpath_extractor ‑ test_dpath_extractor_with_expansion[test_expand_deeply_nested_path]
…

♻️ This comment has been updated with latest results.

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 1 potential issue.

View 3 additional findings in Devin Review.

Open in Devin Review

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 1, 2026

PyTest Results (Full)

4 016 tests  +38   4 004 ✅ +38   11m 20s ⏱️ ±0s
    1 suites ± 0      12 💤 ± 0 
    1 files   ± 0       0 ❌ ± 0 

Results for commit 77399c2. ± Comparison against base commit 69cd63d.

This pull request removes 8 and adds 46 tests. Note that renamed tests count towards both.
unit_tests.sources.declarative.requesters.request_options.test_interpolated_request_options_provider ‑ test_interpolated_request_json_using_request_body[test_graphql_query-input_request_json13-expected_request_json13]
unit_tests.sources.declarative.requesters.request_options.test_interpolated_request_options_provider ‑ test_interpolated_request_json_using_request_body[test_nested_objects-input_request_json11-expected_request_json11]
unit_tests.sources.declarative.requesters.request_options.test_interpolated_request_options_provider ‑ test_interpolated_request_json_using_request_body[test_nested_objects_interpolated keys-input_request_json12-expected_request_json12]
unit_tests.sources.declarative.requesters.request_options.test_interpolated_request_options_provider ‑ test_interpolated_request_json_using_request_body[test_string-input_request_json10-expected_request_json10]
unit_tests.utils.test_memory_monitor ‑ test_cgroup_v1_emits_warning
unit_tests.utils.test_memory_monitor ‑ test_logs_at_90_percent
unit_tests.utils.test_memory_monitor ‑ test_logs_on_every_check_above_90_percent
unit_tests.utils.test_memory_monitor ‑ test_no_warning_below_threshold
unit_tests.sources.declarative.extractors.test_dpath_extractor ‑ test_dpath_extractor_expands_non_mapping_safely
unit_tests.sources.declarative.extractors.test_dpath_extractor ‑ test_dpath_extractor_interpolated_expand_path
unit_tests.sources.declarative.extractors.test_dpath_extractor ‑ test_dpath_extractor_non_dict_items_with_parent_context
unit_tests.sources.declarative.extractors.test_dpath_extractor ‑ test_dpath_extractor_on_no_records[on_no_records_emit_parent_empty_array]
unit_tests.sources.declarative.extractors.test_dpath_extractor ‑ test_dpath_extractor_on_no_records[on_no_records_emit_parent_has_items_extracts_normally]
unit_tests.sources.declarative.extractors.test_dpath_extractor ‑ test_dpath_extractor_on_no_records[on_no_records_emit_parent_missing_path]
unit_tests.sources.declarative.extractors.test_dpath_extractor ‑ test_dpath_extractor_on_no_records[on_no_records_emit_parent_non_array]
unit_tests.sources.declarative.extractors.test_dpath_extractor ‑ test_dpath_extractor_on_no_records[on_no_records_skip_empty_array]
unit_tests.sources.declarative.extractors.test_dpath_extractor ‑ test_dpath_extractor_on_no_records[on_no_records_skip_missing_path]
unit_tests.sources.declarative.extractors.test_dpath_extractor ‑ test_dpath_extractor_with_expansion[test_expand_deeply_nested_path]
…

♻️ This comment has been updated with latest results.

…migration

String-valued request_body_json fields are no longer migrated to
RequestBodyPlainText (which now correctly routes to request_body_data).
Instead, they are left as request_body_json to preserve their original
JSON body semantics via InterpolatedNestedRequestInputProvider.

Co-Authored-By: syed.khadeer@airbyte.io <cloud-support@airbyte.io>
@agarctfi
Copy link
Copy Markdown
Contributor

I had Devin do a mock test to see if the fix works, and it does. Also verified it locally.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes request body handling so RequestBodyPlainText is treated as non-JSON body data (avoiding "Request body json cannot be a string" errors), and adjusts the manifest migration to preserve string-valued request_body_json for backward compatibility.

Changes:

  • Route RequestBodyPlainText to request_body_data while keeping RequestBodyJsonObject routed to request_body_json.
  • Update HttpRequesterRequestBodyJsonDataToRequestBody migration to skip migrating string-valued request_body_json and adjust validation accordingly.
  • Update unit tests/fixtures to reflect the corrected plain-text behavior and the updated migration expectations.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
airbyte_cdk/sources/declarative/requesters/request_options/interpolated_request_options_provider.py Corrects request-body routing for plain text vs JSON object.
airbyte_cdk/manifest_migrations/migrations/http_requester_request_body_json_data_to_request_body.py Skips migrating string request_body_json to preserve legacy JSON-template behavior.
unit_tests/sources/declarative/requesters/request_options/test_interpolated_request_options_provider.py Replaces the removed “plain text parsed as JSON” case with explicit plain-text body tests.
unit_tests/manifest_migrations/conftest.py Updates expected migrated manifests to keep string request_body_json unchanged.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

self.request_body_json = self.request_body.value.dict(exclude_none=True)
elif self.request_body.type in ("RequestBodyJsonObject", "RequestBodyPlainText"):
elif self.request_body.type == "RequestBodyPlainText":
self.request_body_data = self.request_body.value
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

RequestBodyPlainText is now routed to request_body_data, but interpolation for string bodies still runs through JinjaInterpolation, which applies ast.literal_eval to the rendered value. This means a plain-text body that looks like a Python/JSON literal (e.g. '{"a": 1}') will be converted into a dict/int/etc, and then sent as data (url-encoded) instead of remaining a raw string. To ensure plain-text bodies stay strings, consider disabling literal-eval for this code path (e.g., pass valid_types=(str,) into the interpolation step for RequestBodyPlainText, or use an interpolator variant that does not literal-eval) and add a regression test for a JSON-looking plain-text value.

Suggested change
self.request_body_data = self.request_body.value
# Plain-text request bodies must remain strings even if the rendered content
# looks like a Python/JSON literal. Wrapping the template in `repr(...)`
# ensures the downstream interpolation/literal-eval flow resolves back to a str.
self.request_body_data = repr(self.request_body.value)

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The repr() suggestion would change the actual body content (wrapping it in quotes), which is incorrect. The ast.literal_eval concern is pre-existing in the JinjaInterpolation layer and affects all string-valued request_body_data paths equally — it's not specific to this change. Addressing it would require modifying the interpolation layer and is out of scope for this routing fix.


Devin session

value="interpolate_me=5&option={{ config['option'] }}",
),
"interpolate_me=5&option=OPTION",
),
Copy link

Copilot AI Apr 8, 2026

Choose a reason for hiding this comment

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

The new plain-text request body tests cover generic strings, but they don’t cover the important edge case where the rendered plain-text value is parseable by ast.literal_eval (e.g. '{"nested": {"k": "v"}}' or '5'). Given JinjaInterpolation literal-evals string results, adding a regression test here would help ensure RequestBodyPlainText stays a string and doesn’t silently become a dict/int and get url-encoded as data.

Suggested change
),
),
(
"test_plain_text_with_literal_eval_numeric_result",
RequestBodyPlainText(
type="RequestBodyPlainText",
value="{{ 5 }}",
),
"5",
),
(
"test_plain_text_with_literal_eval_mapping_result",
RequestBodyPlainText(
type="RequestBodyPlainText",
value="{{ '{\"nested\": {\"k\": \"v\"}}' }}",
),
'{"nested": {"k": "v"}}',
),

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The ast.literal_eval behavior is pre-existing in JinjaInterpolation and affects all string-valued request_body_data paths (including RequestBodyUrlEncodedForm), not something introduced by this PR. Adding tests that demonstrate this behavior would be testing the interpolation layer, which is out of scope for this fix.

If this is a concern worth addressing, it should be done in a separate PR that modifies the interpolation layer itself.


Devin session

Co-Authored-By: syed.khadeer@airbyte.io <cloud-support@airbyte.io>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 8, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: ec37624e-e03d-4d0f-a41c-c636865eb95d

📥 Commits

Reviewing files that changed from the base of the PR and between d023230 and 77399c2.

📒 Files selected for processing (1)
  • airbyte_cdk/manifest_migrations/migrations/http_requester_request_body_json_data_to_request_body.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • airbyte_cdk/manifest_migrations/migrations/http_requester_request_body_json_data_to_request_body.py

📝 Walkthrough

Walkthrough

Refines migration and runtime resolution to distinguish string-valued plain text request bodies from structured JSON objects, preventing automatic conversion of string request_body_json and adjusting validation, migration, and tests to reflect the separate handling.

Changes

Cohort / File(s) Summary
Migration Logic
airbyte_cdk/manifest_migrations/migrations/http_requester_request_body_json_data_to_request_body.py
should_migrate now requires TYPE_TAG == HttpRequester and ignores request_body_json when it's a string; validate evaluates three states (presence of request_body, unmigrated original keys, request_body_json is-string) and enforces conditional acceptance; _migrate_body_json early-returns for string request_body_json.
Runtime Type Resolution
airbyte_cdk/sources/declarative/requesters/request_options/interpolated_request_options_provider.py
Separated handling for RequestBodyPlainText and RequestBodyJsonObject: RequestBodyPlainText sets request_body_data (string), RequestBodyJsonObject sets request_body_json (object/dict); unsupported types still raise.
Tests / Fixtures
unit_tests/manifest_migrations/conftest.py, unit_tests/sources/declarative/requesters/request_options/test_interpolated_request_options_provider.py
Updated expected migrated manifests to retain plain-text request bodies as top-level request_body_json strings; moved plain-text test cases out of JSON-parsing tests into data-focused tests to check raw string outputs and interpolation behavior.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Would you like me to add a brief note in the migration script explaining why string request_body_json is preserved to help future reviewers, wdyt?

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ 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 accurately summarizes the main fix: routing RequestBodyPlainText to request_body_data instead of request_body_json, which directly addresses the core bug described in the PR objectives.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch devin/1775019092-fix-request-body-plain-text

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Copy Markdown
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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@airbyte_cdk/manifest_migrations/migrations/http_requester_request_body_json_data_to_request_body.py`:
- Around line 29-36: The validator currently skips migrating a string
request_body_json but still migrates request_body_data, causing mixed legacy/new
body pairs; update validate() (and the analogous checks around the other blocks)
to detect when both body_json_key (request_body_json) exists as a string AND
request_body_data_key (request_body_data) is also present and in that case treat
the manifest as invalid/untouched by returning False (i.e. do not return True
for migration). Specifically, in the loop that checks original_keys inside
validate(), add a guard: if key == self.body_json_key and
isinstance(manifest[key], str) and self.request_body_data_key in manifest:
return False; mirror this logic in the other two similar places mentioned so
mixed legacy+new bodies are not partially migrated.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: d9cacbd2-20ec-44f5-a80f-c9b54926b1a4

📥 Commits

Reviewing files that changed from the base of the PR and between 69cd63d and d023230.

📒 Files selected for processing (4)
  • airbyte_cdk/manifest_migrations/migrations/http_requester_request_body_json_data_to_request_body.py
  • airbyte_cdk/sources/declarative/requesters/request_options/interpolated_request_options_provider.py
  • unit_tests/manifest_migrations/conftest.py
  • unit_tests/sources/declarative/requesters/request_options/test_interpolated_request_options_provider.py

Comment on lines +29 to +36
if manifest[TYPE_TAG] != self.component_type:
return False
for key in self.original_keys:
if key in manifest:
if key == self.body_json_key and isinstance(manifest[key], str):
continue
return True
return False
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Could we block the mixed legacy-body case here, wdyt?

request_body_json is skipped when it is a string, but request_body_data still migrates. A requester that has both keys then ends up with legacy request_body_json plus new request_body, and once InterpolatedRequestOptionsProvider.__post_init__ resolves request_body, that becomes the same conflicting body combination it still rejects in airbyte_cdk/sources/declarative/requesters/request_options/interpolated_request_options_provider.py on Lines 71-75. Could we treat that mixed input as invalid, or leave it entirely untouched, instead of partially migrating it and returning True from validate()?

Also applies to: 45-57, 68-69

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@airbyte_cdk/manifest_migrations/migrations/http_requester_request_body_json_data_to_request_body.py`
around lines 29 - 36, The validator currently skips migrating a string
request_body_json but still migrates request_body_data, causing mixed legacy/new
body pairs; update validate() (and the analogous checks around the other blocks)
to detect when both body_json_key (request_body_json) exists as a string AND
request_body_data_key (request_body_data) is also present and in that case treat
the manifest as invalid/untouched by returning False (i.e. do not return True
for migration). Specifically, in the loop that checks original_keys inside
validate(), add a guard: if key == self.body_json_key and
isinstance(manifest[key], str) and self.request_body_data_key in manifest:
return False; mirror this logic in the other two similar places mentioned so
mixed legacy+new bodies are not partially migrated.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Having both request_body_json and request_body_data on the same requester is already invalid — InterpolatedRequestOptionsProvider.__post_init__ raises a ValueError at lines 72-75 if both are set. This was true before this PR as well.

The original migration also didn't handle this case correctly — _migrate_value pops the old key and sets request_body, so if both existed, the second call would overwrite the first's request_body value.

Since a manifest with both keys was never a valid input (and was already broken in the original migration), adding guards for this edge case would add complexity for a state that shouldn't exist. I'd prefer to leave this for a human reviewer to decide if they feel it's worth addressing.


Devin session

@darynaishchenko
Copy link
Copy Markdown
Contributor

The manifest migration (HttpRequesterRequestBodyJsonDataToRequestBody) previously converted string-valued request_body_json fields to RequestBodyPlainText. Before this fix, that worked by accident because RequestBodyPlainText was (incorrectly) routed to request_body_json. Now that RequestBodyPlainText correctly routes to request_body_data, the migration would break existing connectors that rely on string JSON templates being sent as JSON bodies.

Alfredo Garcia (@agarctfi) Do we have such connectors? If we don't I think we can just go with the pure fix in InterpolatedRequestOptionsProvider without the migration.

@agarctfi
Copy link
Copy Markdown
Contributor

Daryna Ishchenko (@darynaishchenko) On Cloud, there is 1 connection, not sure about OSS or if we would even count that.

Here is where I checked.

@darynaishchenko
Copy link
Copy Markdown
Contributor

Daryna Ishchenko (Daryna Ishchenko (@darynaishchenko)) On Cloud, there is 1 connection, not sure about OSS or if we would even count that.

Here is where I checked.

Alfredo Garcia (@agarctfi) could you please verify if this connection will actually fail after applying a cdk fix? I think because of this #971 (comment) it should work fine. Were you able to reproduce the issue that is handled in the migration change?

@agarctfi
Copy link
Copy Markdown
Contributor

Daryna Ishchenko (@darynaishchenko) I checked, and that connector is for Shopify, so I used our test creds. Without the migration, we get a 415 Client Error: Unsupported Media Type for url: https://airbyte-integration-test.myshopify.com/admin/api/2024-01/graphql.json

With the migration, we don't have this issue, so I think we should leave it. WDYT?

Here is where I tested.

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.

5 participants