Skip to content

fix: prevent infinite loop when onSuccess is explicitly undefined#4231

Open
MaxwellCalkin wants to merge 1 commit intovercel:mainfrom
MaxwellCalkin:fix/onsuccess-undefined-infinite-loop
Open

fix: prevent infinite loop when onSuccess is explicitly undefined#4231
MaxwellCalkin wants to merge 1 commit intovercel:mainfrom
MaxwellCalkin:fix/onsuccess-undefined-infinite-loop

Conversation

@MaxwellCalkin
Copy link

Summary

Fixes #4218

When onSuccess: undefined is explicitly passed in the options (a common pattern when wrapping useSWR in a custom hook with optional callbacks), mergeConfigs spreads the user config over the defaults, which causes onSuccess: undefined to override the default noop callback. This results in a TypeError when the successful fetch attempts to call config.onSuccess(). The error is caught by the catch block, which triggers onErrorRetry, which re-fetches successfully, which calls undefined() again — creating an infinite request loop.

// Common pattern that triggers the bug
const useMyFetch = ({ onSuccess }: { onSuccess?: (data: Data) => void }) => {
  return useSWR(key, fetcher, {
    onSuccess, // becomes undefined when caller doesn't provide it
  });
};

useMyFetch({}); // infinite loop

Fix

Strip undefined values from the user config object in mergeConfigs before spread-merging, so explicitly passing undefined behaves the same as omitting the property entirely.

Tests

Added 3 test cases:

  • onSuccess: undefined does not cause infinite requests
  • onError: undefined does not cause infinite requests
  • Custom hook wrapper passing optional onSuccess that is undefined

All 3 tests fail without the fix and pass with it.

Transparency note: This PR was authored by an AI (Claude Opus 4.6, Anthropic) operating under the supervision of a human.

🤖 Generated with Claude Code

When a user passes `{ onSuccess: undefined }` (e.g. from an optional
callback in a custom hook wrapper), the spread merge in mergeConfigs
overwrites the default `noop` callback with `undefined`. This causes a
TypeError when the successful fetch tries to call `config.onSuccess()`,
which is caught by the error handler, triggering an error retry, which
succeeds again and throws again -- creating an infinite request loop.

Strip undefined values from user config before merging so they don't
override defaults.

Fixes vercel#4218

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@chatgpt-codex-connector
Copy link

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@codesandbox-ci
Copy link

codesandbox-ci bot commented Mar 8, 2026

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

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.

Infinite loop when passing onSuccess: undefined explicitly

1 participant