Skip to content

fix(client): preserve Prisma.skip through query extension args cloning#29198

Merged
jacek-prisma merged 4 commits intoprisma:mainfrom
veeceey:fix/issue-25845-skip-with-query-extensions
Feb 16, 2026
Merged

fix(client): preserve Prisma.skip through query extension args cloning#29198
jacek-prisma merged 4 commits intoprisma:mainfrom
veeceey:fix/issue-25845-skip-with-query-extensions

Conversation

@veeceey
Copy link
Copy Markdown
Contributor

@veeceey veeceey commented Feb 15, 2026

Problem

When using Prisma.skip with query extensions ($allModels.$allOperations), the skip value gets silently converted to {} during argument cloning, causing runtime validation errors:

Argument `name`: Invalid value provided. Expected String or Null, provided Object.

This happens because deepCloneArgs treats the Skip instance as a regular object and clones it into a plain {}, which then fails the instanceof Skip check downstream in serializeJsonQuery.

Fix

Added isSkip(x) to the early-return condition in deepCloneValue, so Skip instances pass through cloning untouched — the same pattern already used for ObjectEnumValue and FieldRef.

Tests

  • Added unit tests for deepCloneArgs verifying Skip preservation through cloning (top-level, nested, in arrays)
  • Added functional tests for Prisma.skip used with $allModels.$allOperations query extensions covering create, findMany (input fields and top-level args), include, and select

Fixes #25845

Summary by CodeRabbit

  • Bug Fixes

    • Preserve "skip" markers when cloning or processing arguments so skip behavior remains consistent and immutable across operations, including when query extensions are used.
  • Tests

    • Added tests validating skip preservation for top-level values, nested objects, arrays, and behavior across query extensions; also confirm regular values are deep-cloned (originals remain unchanged).

When using `Prisma.skip` with query extensions that define
`$allModels.$allOperations`, the `deepCloneArgs` utility would clone
Skip instances into plain `{}` objects, breaking the `instanceof`
check and causing validation errors like "Expected String, provided
Object".

The fix adds an `isSkip` check to `deepCloneValue` so Skip instances
pass through cloning unchanged, consistent with how ObjectEnumValue
and FieldRef are already handled.

Fixes prisma#25845
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Feb 15, 2026

CLA assistant check
All committers have signed the CLA.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 15, 2026

No actionable comments were generated in the recent review. 🎉


Walkthrough

deepCloneArgs was modified to treat Skip instances as non-cloneable so Prisma.skip is preserved during argument cloning. New unit tests and functional tests (with query extensions) were added to verify Skip preservation in nested objects, arrays, top-level values, and extended query flows.

Changes

Cohort / File(s) Summary
deepCloneArgs implementation & unit tests
packages/client/src/runtime/utils/deepCloneArgs.ts, packages/client/src/runtime/utils/deepCloneArgs.test.ts
Imported isSkip and updated deepCloneValue to bypass deep cloning for Skip instances. Added unit tests asserting Skip is preserved for nested objects, arrays, top-level values, and that regular objects are deep-cloned.
Functional tests: Skip with query extensions
packages/client/tests/functional/skip/test.ts
Added an "after query extension" test suite using a $allModels.$allOperations query extension to verify Prisma.skip propagates through create, findMany, findFirstOrThrow and include/select scenarios without causing validation errors.
🚥 Pre-merge checks | ✅ 5 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Merge Conflict Detection ⚠️ Warning ❌ Merge conflicts detected (13 files):

⚔️ README.md (content)
⚔️ packages/client-generator-js/package.json (content)
⚔️ packages/client-generator-ts/package.json (content)
⚔️ packages/client/package.json (content)
⚔️ packages/client/src/runtime/utils/deepCloneArgs.ts (content)
⚔️ packages/client/tests/functional/skip/test.ts (content)
⚔️ packages/engines/package.json (content)
⚔️ packages/fetch-engine/package.json (content)
⚔️ packages/internals/package.json (content)
⚔️ packages/migrate/package.json (content)
⚔️ packages/migrate/src/commands/MigrateDiff.ts (content)
⚔️ packages/schema-files-loader/package.json (content)
⚔️ pnpm-lock.yaml (content)

These conflicts must be resolved before merging into main.
Resolve conflicts locally and push changes to this branch.
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly describes the main fix: preserving Prisma.skip through query extension args cloning, which matches the changeset modifications to deepCloneArgs.
Linked Issues check ✅ Passed The PR implements all coding requirements from issue #25845: modifying deepCloneArgs to treat Skip instances as non-cloneable, adding unit tests for deepCloneArgs, and adding functional tests for Prisma.skip with query extensions.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing the Skip preservation issue: deepCloneArgs.ts adds isSkip guard, deepCloneArgs.test.ts adds unit tests, and skip/test.ts adds functional tests for the extension scenario.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
⚔️ Resolve merge conflicts (beta)
  • Auto-commit resolved conflicts to branch fix/issue-25845-skip-with-query-extensions
  • Post resolved changes as copyable diffs in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

…p tests

Addresses CodeRabbit review nitpick: the prisma.$extends() query extension
setup was duplicated across all five tests. Move it to a shared const at the
describe block level to reduce repetition.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

@veeceey
Copy link
Copy Markdown
Contributor Author

veeceey commented Feb 16, 2026

@CLAassistant check

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq bot commented Feb 16, 2026

Merging this PR will degrade performance by 99.26%

❌ 1 regressed benchmark
✅ 46 untouched benchmarks

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
compile findUnique simple 877.9 µs 119,211 µs -99.26%

Comparing veeceey:fix/issue-25845-skip-with-query-extensions (75b9d81) with main (b0385e1)

Open in CodSpeed

@jacek-prisma jacek-prisma merged commit 9865dcb into prisma:main Feb 16, 2026
242 of 244 checks passed
jacek-prisma added a commit that referenced this pull request Feb 19, 2026
#29198)

## Problem

When using `Prisma.skip` with query extensions
(`$allModels.$allOperations`), the skip value gets silently converted to
`{}` during argument cloning, causing runtime validation errors:

```
Argument `name`: Invalid value provided. Expected String or Null, provided Object.
```

This happens because `deepCloneArgs` treats the `Skip` instance as a
regular object and clones it into a plain `{}`, which then fails the
`instanceof Skip` check downstream in `serializeJsonQuery`.

## Fix

Added `isSkip(x)` to the early-return condition in `deepCloneValue`, so
`Skip` instances pass through cloning untouched — the same pattern
already used for `ObjectEnumValue` and `FieldRef`.

## Tests

- Added unit tests for `deepCloneArgs` verifying Skip preservation
through cloning (top-level, nested, in arrays)
- Added functional tests for `Prisma.skip` used with
`$allModels.$allOperations` query extensions covering create, findMany
(input fields and top-level args), include, and select

Fixes #25845

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Preserve "skip" markers when cloning or processing arguments so skip
behavior remains consistent and immutable across operations, including
when query extensions are used.

* **Tests**
* Added tests validating skip preservation for top-level values, nested
objects, arrays, and behavior across query extensions; also confirm
regular values are deep-cloned (originals remain unchanged).
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Jacek Malec <malec@prisma.io>
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.

strictUndefinedChecks does not work with query extensions

3 participants