a2aproject / a2aproject/a2a-js

[Bug]: Authentication fetch wrapper drops Headers entries and corrupts tuple-array headers

Open
#716 2 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
613
Forks
169
Avg merge
1d 6h
Merged PRs (30d)
21

Description

## What happened

`createAuthenticatingFetchWithRetry` preserves request headers supplied as a plain object, but loses entries supplied through a `Headers` instance and corrupts a tuple-array `HeadersInit`. This affects both the initial request and the authentication retry.

With `A2A-Version: 1.0` and `Content-Type: application/json`:

- Plain object: both headers are preserved.
- `new Headers(...)`: both headers disappear; only the authentication handler's Authorization header remains.
- `[['A2A-Version', '1.0'], ['Content-Type', 'application/json']]`: the request instead contains headers named `0` and `1`, with comma-joined pair values.

## What I expected

The fetch wrapper should preserve caller headers for all supported `HeadersInit` representations, on both the initial request and retry.

## Steps to reproduce

1. Wrap a mock fetch using `createAuthenticatingFetchWithRetry`, with `headers()` returning an Authorization header and `shouldRetryWithHeaders()` returning a refreshed Authorization header.
2. Have the mock capture `new Request(input, init).headers`, return 401 on its first invocation and 200 on its second.
3. Call the wrapped fetch with `headers: new Headers({ 'A2A-Version': '1.0', 'Content-Type': 'application/json' })`.
4. Observe that both captured requests lack the supplied version and content-type headers.
5. Repeat using a plain object and then a tuple array; observe the comparison above.

## Additional context

This can affect version negotiation, content-type handling, and custom extension headers when composing the authentication helper with other fetch wrappers. The helper is typed as `typeof fetch` and accepts `RequestInit`, whose headers support all these representations.

Normalizing the caller's headers through `Headers` before merging would support those representations while allowing the intended precedence to be preserved.

Fetch standard: https://fetch.spec.whatwg.org/#headers-class

Contributor guide

Open the contributing guide

Research direction

Look at the `createAuthenticatingFetchWithRetry` function, likely in a file like `src/fetch-wrapper.ts`. Examine how it merges headers from the caller's request init with the authentication headers. The bug is in header normalization; the fix is to convert all header inputs to a `Headers` instance before merging. Write a test that reproduces the issue with the three header representations (object, Headers instance, tuple array) and verifies they are preserved after the fix.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, typescript
Domain
api, authentication
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
65/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.