From 348d2cc9ac95f7fb621622355ed1ef1a837e7536 Mon Sep 17 00:00:00 2001 From: JSap0914 Date: Wed, 17 Jun 2026 20:28:01 +0900 Subject: [PATCH] fix: throw proper immer error when applyPatches path traverses null typeof null === "object" causes isObjectish(null) to return true, silently bypassing the path-resolution guard inside applyPatches_. Traversal then calls getArchtype(null) which accesses null[DRAFT_STATE] and crashes with a native TypeError instead of immer error 18 ("Cannot apply patch, path doesn't resolve"). Add an explicit null check alongside isObjectish so the guard fires correctly and the caller receives the expected immer error message. Fixes: applyPatches({a: null}, [{op: 'add', path: ['a', 'b'], value: 1}]) --- __tests__/patch.js | 9 +++++++++ src/plugins/patches.ts | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/__tests__/patch.js b/__tests__/patch.js index c7dbeaf6b..7e26cb418 100644 --- a/__tests__/patch.js +++ b/__tests__/patch.js @@ -1596,3 +1596,12 @@ describe("RTK-5159: Patch path truncation bug", () => { expect(patches[0].path).toEqual(["queries", "queryKey", "data", "items", 1]) }) }) +test("applyPatches throws proper immer error when intermediate path value is null", () => { + // isObjectish(null) === true (typeof null === "object"), so the null check + // inside applyPatches_ was missing; navigating into null threw a native + // TypeError instead of immer's own "path doesn't resolve" error. + const isProd = process.env.NODE_ENV === "production" + expect(() => { + applyPatches({a: null}, [{op: "add", path: ["a", "b"], value: 1}]) + }).toThrow(isProd ? "18" : "Cannot apply patch, path doesn't resolve: a/b") +}) diff --git a/src/plugins/patches.ts b/src/plugins/patches.ts index ca6ded45a..08c7d0f62 100644 --- a/src/plugins/patches.ts +++ b/src/plugins/patches.ts @@ -345,7 +345,8 @@ export function enablePatches() { die(errorOffset + 3) if (isFunction(base) && p === PROTOTYPE) die(errorOffset + 3) base = get(base, p) - if (!isObjectish(base)) die(errorOffset + 2, path.join("/")) + if (base === null || !isObjectish(base)) + die(errorOffset + 2, path.join("/")) } const type = getArchtype(base)