Skip to content

[SDK] Fix x402 retries losing effective request headers - #9047

Open
snuff12 wants to merge 3 commits into
thirdweb-dev:mainfrom
snuff12:sdk/fix-x402-retry-headers
Open

snuff12 wants to merge 3 commits into
thirdweb-dev:mainfrom
snuff12:sdk/fix-x402-retry-headers

Conversation

@snuff12

@snuff12 snuff12 commented Nov 2, 2026 •

Copy link
Copy Markdown

Preserve the effective application headers when wrapFetchWithPayment retries an x402 request.

  • Normalize HeadersInit entries once during native option conversion, including Request-owned headers.
  • Preserve Fetch replacement precedence for explicit and empty init.headers overrides.
  • Set payment headers case-insensitively without mutating caller-owned headers.
  • Add x402 v1/v2 regression coverage and a patch changeset.

Fixes #9045

Validation

  • 118 focused wrapper/schema tests pass with an offline MSW fixture; 20 regression cases fail against the unchanged base.
  • SDK and its engine/insight workspace dependencies build successfully; pnpm fix, pnpm lint, and a focused test type check pass in the selected workspace checkout.
  • Two independent local reviewers checked this exact signed commit and ran separate native-fetch/loopback tests (results recorded locally).
  • Both changes together: 148 tests, Biome, and SDK type check pass.

The upstream test global setup starts external RPC/Anvil services; these targeted tests ran with an offline configuration instead. No real payment settlement was performed.

The Request-body fix is a separate change. Both PRs target main independently. Their callback declaration overlaps; after either is merged, the other will need a rebase. The combined behavior has been tested.

When applying both fixes, construct the replay Request from the normalized initialInit and keep the fallback init lazy.

Summary by CodeRabbit

  • Bug Fixes
    • Payment retries now preserve the effective request headers across supported input formats, including headers inherited from a Request.
    • Explicit header overrides are respected, including empty overrides, and omitted headers continue to inherit from the original request.
    • Payment-related headers are added without changing the caller’s original headers.

@snuff12
snuff12 requested review from a team as code owners November 2, 2026 07:29
@changeset-bot

changeset-bot Bot commented Nov 2, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: aceb057

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 3 packages
Name Type
thirdweb Patch
@thirdweb-dev/wagmi-adapter Patch
wagmi-inapp Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercel Bot commented Nov 2, 2026

Copy link
Copy Markdown

@snuff12 is attempting to deploy a commit to the thirdweb Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions github-actions Bot added packages SDK Involves changes to the thirdweb SDK labels Nov 2, 2026
@coderabbitai

coderabbitai Bot commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 5de4df2d-3cc7-4c71-b151-e757ae6c484f
Commits

Reviewing files that changed from the base of the PR and between 940b374 and aceb057.

Files selected for processing: 4
  • .changeset/preserve-x402-retry-headers.md
  • packages/thirdweb/src/x402/fetchWithPayment.headers.test.ts
  • packages/thirdweb/src/x402/fetchWithPayment.test.ts
  • packages/thirdweb/src/x402/fetchWithPayment.ts

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 3 remain after this review.

Walkthrough

wrapFetchWithPayment now captures effective request headers and uses them to build payment retries for x402 v1 and v2. Regression tests cover native HeadersInit forms, Request header inheritance and overrides, and preservation of caller-owned headers.

Changes

x402 payment retry header handling

Layer / File(s) Summary
Capture effective request headers
packages/thirdweb/src/x402/fetchWithPayment.ts, packages/thirdweb/src/x402/fetchWithPayment.headers.test.ts
The initial fetch uses a proxy to preserve access to the caller’s RequestInit properties and captures headers from init.headers or the input Request. Tests cover getter order, receiver binding, and single reads of accessors.
Build retries from captured headers
packages/thirdweb/src/x402/fetchWithPayment.ts, packages/thirdweb/src/x402/fetchWithPayment.headers.test.ts, packages/thirdweb/src/x402/fetchWithPayment.test.ts, .changeset/preserve-x402-retry-headers.md
The retry copies captured headers into a Headers object before setting payment and response-exposure headers. Tests cover header input forms, override behavior, caller-header immutability, and payment-header selection for both protocol versions. Existing assertions now inspect headers through the Headers API. The changeset records a thirdweb patch.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix · Severity of issue fixed: Medium

Suggested labels: packages, SDK

Suggested reviewers: joaquim-verges, 0xfirekeeper

Merge Risk: Minimal · up to aceb0

The header-preservation change appears ready to merge after normal checks.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentat… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title clearly identifies the main change: fixing x402 retries that lose effective request headers. It is concise and specific.
Description check Passed The description explains the change, lists the affected behavior, references issue #9045, documents validation, and notes reviewer considerations. It does not use the exact template headings, but it p…
Linked Issues check Passed Issue #9045 is directly linked and open. fetchWithPayment.ts now normalizes headers through Headers, captures Request-owned headers when init.headers is undefined, preserves explicit and empty o…
Out of Scope Changes check Passed The changed implementation directly addresses issue #9045. The new regression tests verify the required retry behavior. The test assertion updates and patch changeset support that implementation. No u…
Full details: Description check

Explanation

The description explains the change, lists the affected behavior, references issue #9045, documents validation, and notes reviewer considerations. It does not use the exact template headings, but it provides the required notes and testing information.

Full details: Linked Issues check

Explanation

Issue #9045 is directly linked and open. fetchWithPayment.ts now normalizes headers through Headers, captures Request-owned headers when init.headers is undefined, preserves explicit and empty overrides, and reuses the captured snapshot for the paid retry. Headers.set replaces payment and exposure headers case-insensitively without changing caller-owned inputs. The added suite covers x402 v1 and v2, object/Headers/tuple/Request inputs, undefined and empty overrides, accessor reads, and caller mutation. The patch changeset is present.

Full details: Out of Scope Changes check

Explanation

The changed implementation directly addresses issue #9045. The new regression tests verify the required retry behavior. The test assertion updates and patch changeset support that implementation. No unrelated change is shown in the reviewed diff.

Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 2 functions across 3 files. (1 skipped: 1 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

Finishing Touches
Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

This branch has not been deployed

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

Labels

packages SDK Involves changes to the thirdweb SDK

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[SDK] x402 payment retry drops HeadersInit and Request-owned headers

1 participant