diff --git a/.changeset/fix-deterministic-request-id.md b/.changeset/fix-deterministic-request-id.md new file mode 100644 index 000000000..89cea3661 --- /dev/null +++ b/.changeset/fix-deterministic-request-id.md @@ -0,0 +1,5 @@ +--- +"openapi-fetch": patch +--- + +Replace `Math.random()` with a monotonic counter in `randomID()`. `Math.random()` is a non-deterministic side effect that can interfere with frameworks that cache or deduplicate `fetch()` calls (e.g. Next.js React Server Components). The counter produces unique IDs within a process while being deterministic across runs. diff --git a/packages/openapi-fetch/src/index.js b/packages/openapi-fetch/src/index.js index 4c7250fb0..d067fd107 100644 --- a/packages/openapi-fetch/src/index.js +++ b/packages/openapi-fetch/src/index.js @@ -9,12 +9,17 @@ const supportsRequestInitExt = () => { ); }; +/** Counter for deterministic request ID generation */ +let _idCounter = 0; + /** - * Returns a cheap, non-cryptographically-secure random ID - * Courtesy of @imranbarbhuiya (https://github.com/imranbarbhuiya) + * Returns a cheap, non-cryptographically-secure unique ID. + * Uses a monotonic counter instead of Math.random() so IDs are + * deterministic within a process, which is compatible with + * frameworks that cache or deduplicate fetch calls (e.g. Next.js). */ export function randomID() { - return Math.random().toString(36).slice(2, 11); + return (++_idCounter).toString(36); } /**