Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 21, 2026

When a request with deduplication is canceled, it was rejecting the shared deferred, causing all waiting requests to fail with ERR_CANCELED. Subsequent requests for the same resource would fail even though they weren't canceled.

Example of the issue:

const axios = setupCache(Axios.create());

const controller = new AbortController();
const req1 = axios.get('/api/data', { signal: controller.signal });
const req2 = axios.get('/api/data'); // Deduplicates, waits on req1's deferred

controller.abort(); // Aborts req1

await req1; // ❌ Fails with ERR_CANCELED (expected)
await req2; // ❌ Also fails with ERR_CANCELED (bug - should succeed)

Changes

Response interceptor (src/interceptors/response.ts)

  • ERR_CANCELED now resolves the deferred instead of rejecting it
  • Waiting requests proceed with their own network call
  • Cache cleanup remains unchanged

Test coverage (test/interceptors/abort-request.test.ts)

  • Sequential abort/retry scenario
  • Immediate abort/retry (issue reproduction)
  • Multiple concurrent requests after abort

Updated expectations (test/interceptors/response.test.ts)

  • "Cancelled deferred" test now expects waiting requests to succeed

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • REDACTED-url.lan
    • Triggering command: /usr/local/bin/node /usr/local/bin/node --import ./test/setup.js --enable-source-maps /home/REDACTED/work/axios-cache-interceptor/axios-cache-interceptor/test/interceptors/stale-if-error.test.ts (dns block)
    • Triggering command: /usr/local/bin/node /usr/local/bin/node --import ./test/setup.js --enable-source-maps /home/REDACTED/work/axios-cache-interceptor/axios-cache-interceptor/test/interceptors/stale-if-error.test.ts test/interceptors/hydrate.test.ts test/interceptors/last-modified.test.ts test/interceptors/request.test.ts test/interceptors/response.test.ts test/interceptors/stale-if-error.test.ts test/interceptors/util.test.ts test/interceptors/vary.test.ts (dns block)
    • Triggering command: /usr/local/bin/node /usr/local/bin/node --import ./test/setup.js --enable-source-maps /home/REDACTED/work/axios-cache-interceptor/axios-cache-interceptor/test/interceptors/stale-if-error.test.ts --enable-sourceOUTPUT (dns block)
  • REDACTED.url.lan
    • Triggering command: /usr/local/bin/node /usr/local/bin/node --import ./test/setup.js --enable-source-maps /home/REDACTED/work/axios-cache-interceptor/axios-cache-interceptor/test/interceptors/response.test.ts (dns block)
    • Triggering command: /usr/local/bin/node /usr/local/bin/node --import ./test/setup.js --enable-source-maps /home/REDACTED/work/axios-cache-interceptor/axios-cache-interceptor/test/interceptors/stale-if-error.test.ts (dns block)
    • Triggering command: /usr/local/bin/node /usr/local/bin/node --import ./test/setup.js --enable-source-maps /home/REDACTED/work/axios-cache-interceptor/axios-cache-interceptor/test/interceptors/response.test.ts test/interceptors/hydrate.test.ts test/interceptors/last-modified.test.ts test/interceptors/request.test.ts test/interceptors/response.test.ts test/interceptors/stale-if-error.test.ts test/interceptors/util.test.ts test/interceptors/vary.test.ts (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

Original prompt

This section details on the original issue you should resolve

<issue_title>Bug: request fails when a previous request with the same parameters is aborted</issue_title>
<issue_description>### What happened?

Imagine an application that fetches some data when its state changes, and cancels the previous request (even if the relevant parameters for the request haven't necessarily changed).
This might look something like this:

import Axios from "https://cdn.skypack.dev/[email protected]";
import { setupCache } from "https://cdn.skypack.dev/[email protected]";

const axios = setupCache(Axios.create(), {
  interpretHeader: false,
  debug: console.log
});

const abortControler = new AbortController();
const req1 = axios.get("https://dummyjson.com/products", { signal: abortControler.signal });

setTimeout(() => {
  abortControler.abort();
  const req2 = axios.get("https://dummyjson.com/products");
  req2
    .then(() => console.log("this won't happen"))
    .catch(() => console.log("second request has also failed."));
}, 10)

(see https://jsfiddle.net/x5t071yh/3/ )

What happens is that when cache-interceptor is enabled, the second request will also fail. This is counterintuitive.

cheers,
Mehran

axios-cache-interceptor version

v1.11.3

Node / Browser Version

Node 24.12.0 / Chrome 144

Axios Version

v1.13.2

What storage is being used

Memory Storage

Relevant debugging log output

[
    {
        "id": "-95760698",
        "msg": "Making network request",
        "data": {
            "overrideCache": false,
            "cacheState": "empty"
        }
    },
    {
        "id": "-95760698",
        "msg": "Caching response",
        "data": {
            "ttl": 300000,
            "interpretHeader": false
        }
    },
    {
        "id": "-95760698",
        "msg": "Found waiting deferred(s) and resolve them"
    },
    {
        "id": "-95760698",
        "msg": "Response cached successfully",
        "data": {
            "state": "cached",
            "ttl": 300000
        }
    },
    {
        "id": "-95760698",
        "msg": "Using cached response"
    },
    {
        "id": "-95760698",
        "msg": "Returned cached response"
    }
]
```</issue_description>

<agent_instructions>try to reproduce this issue and either open a pr fixing the issue or open a PR adding documentation to teach which options or things the dev must to do solve this problem</agent_instructions>

## Comments on the Issue (you are @copilot in this section)

<comments>
</comments>

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI and others added 2 commits January 21, 2026 06:23
- When a request is aborted (ERR_CANCELED), resolve the deferred instead of rejecting it
- This allows other waiting requests to proceed with their own network call
- Added comprehensive tests to verify the fix
- Updated existing test to reflect the new expected behavior

Co-authored-by: arthurfiorette <[email protected]>
- Add proper type for Promise in abort request test
- Fix linter warnings and formatting

Co-authored-by: arthurfiorette <[email protected]>
Copilot AI changed the title [WIP] Fix request failure when previous request aborted Fix: canceled requests no longer propagate errors to deduplicated requests Jan 21, 2026
Copilot AI requested a review from arthurfiorette January 21, 2026 06:28
@arthurfiorette arthurfiorette marked this pull request as ready for review January 21, 2026 06:33
Copilot AI review requested due to automatic review settings January 21, 2026 06:33
@codecov
Copy link

codecov bot commented Jan 21, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.77%. Comparing base (41c3a24) to head (44dc1dd).
⚠️ Report is 5 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1172   +/-   ##
=======================================
  Coverage   98.77%   98.77%           
=======================================
  Files          20       20           
  Lines        3092     3099    +7     
  Branches      272      275    +3     
=======================================
+ Hits         3054     3061    +7     
  Misses         36       36           
  Partials        2        2           

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@arthurfiorette arthurfiorette merged commit 2aea76d into main Jan 21, 2026
11 checks passed
@arthurfiorette arthurfiorette deleted the copilot/fix-aborted-request-error branch January 21, 2026 06:35
Copy link
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

This pull request fixes a bug where canceled requests with deduplication were incorrectly propagating ERR_CANCELED errors to all waiting deduplicated requests, causing subsequent requests for the same resource to fail even though they weren't canceled.

Changes:

  • Modified response interceptor to resolve deferred promises instead of rejecting them when a request is canceled
  • Updated test expectations to reflect that waiting requests should succeed after a cancellation
  • Added comprehensive test coverage for various abort scenarios

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/interceptors/response.ts Modified error handling to resolve deferred for ERR_CANCELED instead of rejecting, allowing waiting requests to make their own network calls
test/interceptors/response.test.ts Updated existing test expectations to verify waiting requests succeed after first request is canceled
test/interceptors/abort-request.test.ts Added new comprehensive test suite covering sequential abort/retry, immediate abort/retry, and multiple concurrent requests scenarios

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

Comment on lines +327 to +337
// p2 should succeed by making its own network call
// This is the fix for the issue where canceled requests were incorrectly
// propagating errors to other waiting requests
const result = await promise;
assert.equal(result.cached, false); // Made a new network call
assert.ok(result.data);

const storage = await axios.storage.get(id);

// Cache should be empty since the request was cancelled
assert.equal(storage.state, 'empty');
// Cache should now be populated from the successful second request
assert.equal(storage.state, 'cached');
Copy link

Copilot AI Jan 21, 2026

Choose a reason for hiding this comment

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

The test name "Cancelled deferred propagates error to all waiting requests" is now misleading since the test validates that waiting requests should succeed (not receive the error). Consider updating the test name to reflect the new behavior, such as "Cancelled request does not propagate error to waiting deduplicated requests" or "Waiting requests succeed after first request is cancelled".

Copilot uses AI. Check for mistakes.
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.

Bug: request fails when a previous request with the same parameters is aborted

2 participants