Skip to content

fix(low-code): identify the failing response when JSON decoding fails - #1108

Draft
Airbyte Support (Airbyte-Support) wants to merge 2 commits into
mainfrom
devin/1786079355-json-decoder-diagnostics
Draft

fix(low-code): identify the failing response when JSON decoding fails#1108
Airbyte Support (Airbyte-Support) wants to merge 2 commits into
mainfrom
devin/1786079355-json-decoder-diagnostics

Conversation

@Airbyte-Support

Copy link
Copy Markdown
Contributor

Summary

JsonDecoder.decode deliberately swallows every decode exception and yields {} so that a bad body looks like "no records". That is fine as a resilience choice, but the only trace left behind is JsonParser's terse line:

Failed to parse JSON data using json library. Expecting value: line 1 column 1 (char 0)

No URL, no status code, no content type, no body. When a store or API intermittently answers HTTP 200 with an empty or HTML body, a Cloud sync reports success with 0 records and nothing in the log says which request went wrong.

This adds that context at the JsonDecoder boundary, where the requests.Response is still in hand:

except Exception as exc:
    logger.error(filter_secrets(
        "Failed to decode JSON response: "
        f"method={...}, url={response.url}, status_code={response.status_code}, "
        f"content_type={...}, body_length={...}, body_preview={...!r}, error={exc}"
    ))
    yield {}

Sample output for a 200 with an empty body:

Failed to decode JSON response: method=GET, url=https://example.com/wp-json/wc/v3/orders?modified_after=2026-08-06T05%3A00%3A00&modified_before=2026-08-07T05%3A07%3A45, status_code=200, content_type=application/json, body_length=0, body_preview='', error=Response JSON data failed to be parsed. See logs for more information.

Notes on the choices:

  • Failure semantics are unchanged. It still yields {}, so no connector starts failing on bodies it used to tolerate.
  • filter_secrets is required, not cosmetic. Some connectors put API keys in query params, so response.url and echoed bodies can carry credentials. The body preview is capped at 200 bytes.
  • Legitimately empty responses stay silent. [] and {} reach the if not has_yielded: yield {} path without raising, so they produce no log line. Covered by a test that asserts zero log records.
  • JsonParser._parse_json's existing logger.error is left at error level: CompositeRawDecoder uses that parser directly, without going through JsonDecoder, so lowering it would blind those paths.

Found while diagnosing a WooCommerce Cloud connection whose orders stream reported 0 records on every incremental sync. The store was answering some /orders requests with a non-JSON 200; the terse log gave no way to tell which window was affected.

Follow-up worth a separate look, not addressed here: each failed response emits the parse error three times, i.e. the response body appears to be decoded three times per read.

Test plan

  • New unit tests in unit_tests/sources/declarative/decoders/test_json_decoder.py cover an empty 200 body, an HTML 200 body, secret filtering of URL and body, and the empty-JSON-array case asserting no log output.
  • pytest unit_tests/sources/declarative/decoders/test_json_decoder.py → 10 passed; ruff check, ruff format --check, and mypy airbyte_cdk all clean.
  • Verified end to end by running the real source-woocommerce manifest through source-declarative-manifest read against a local mock serving HTTP 200 with an empty body and with <html>error</html>: both produce the new line, both still exit 0 with 0 records and an unchanged cursor.

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

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, CI, and merge conflict monitoring

@github-actions

github-actions Bot commented Aug 7, 2026

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/1786079355-json-decoder-diagnostics#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/1786079355-json-decoder-diagnostics

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.

Comment on lines +49 to +54
filter_secrets(
"Failed to decode JSON response: "
f"method={request_method}, url={response.url}, status_code={response.status_code}, "
f"content_type={response.headers.get('Content-Type')}, body_length={len(body)}, "
f"body_preview={body_preview!r}, error={exc}"
)
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

PyTest Results (Fast)

4 187 tests  +4   4 175 ✅ +4   7m 44s ⏱️ + 1m 30s
    1 suites ±0      12 💤 ±0 
    1 files   ±0       0 ❌ ±0 

Results for commit 66f7da2. ± Comparison against base commit 5c99925.

♻️ This comment has been updated with latest results.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

PyTest Results (Full)

4 190 tests  +4   4 178 ✅ +4   12m 27s ⏱️ +31s
    1 suites ±0      12 💤 ±0 
    1 files   ±0       0 ❌ ±0 

Results for commit 66f7da2. ± Comparison against base commit 5c99925.

♻️ This comment has been updated with latest results.

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.

2 participants