docs/plans/agent-native/007-skill-api-pitfalls.md
Document the client API behaviors that reliably trip up both humans and agents, with
engine-verified semantics (sources below are the query-engine test suite and compiler
sources at the matching engines revision). Land as references/ additions to the existing
prisma-client-api skill in prisma/skills, plus a preview-feature guidance reference.
Verified in query-compiler/core/src/query_graph_builder/extractors/filters/mod.rs and pinned
by engine tests (filters.rs: empty_and / empty_or / empty_not):
| Filter | Result | SQL rendering |
|---|---|---|
AND: [] | matches all rows | 1=1 |
OR: [] | matches no rows | 1=0 |
NOT: [] | matches all rows | 1=1 |
The practical trap: building OR clauses dynamically and passing an empty array returns zero
rows — usually the opposite of intent. Rule of thumb for generated filters: omit the operator
entirely (or use undefined, which is dropped) instead of passing []. Note the validation
edge: nested arrays like AND: [[]] throw PrismaClientValidationError.
some / every / none relation filtersVerified in engine tests (extended_relation_filters.rs, self_relation.rs):
some: {} → "has at least one related row"; none: {} → "has no related rows".every is vacuously true on empty relations: every: { ... } includes parents with
zero related rows. every means "no counterexample", not "has rows and all match".some: { OR: [] } matches nothing; every: { OR: [] } matches only parents with zero
related rows. Document these as worked examples.AND: [{ rel: { some: {} } }, { rel: { every: cond } }].undefined valuesVerified in packages/client/src/runtime/core/jsonProtocol/serializeJsonQuery.ts:
undefined object value is silently dropped from the query.
The catastrophic case: deleteMany({ where: { id: undefined } }) becomes
deleteMany({ where: {} }) — it deletes every row. Same for updateMany.strictUndefinedChecks preview feature, the same input throws
PrismaClientValidationError ("explicitly undefined values are not allowed");
Prisma.skip expresses intentional omission. Array elements always throw, feature or not.strictUndefinedChecks in agent-managed projects; never build
where objects by spreading possibly-undefined values into destructive operations without
the feature on.fullTextSearch is stabilized for MySQL, but on PostgreSQL the renamed
fullTextSearchPostgres preview remains limited. Recommendation: on PostgreSQL use raw SQL
or TypedSQL with tsvector/tsquery (and a GIN index) instead of the preview API; include
a worked TypedSQL example. Cross-reference task 008 (unhiding typedSql).A "when to suggest what" table for the currently-active preview features, so agents propose
them at the right moment instead of never or always: relationJoins (deep includes; see task
009), nativeDistinct (distinct is otherwise in-memory), strictUndefinedChecks (see above),
views, partialIndexes, postgresqlExtensions, shardKeys, fullTextSearchPostgres.
For each: symptom that should trigger the suggestion, provider support, maturity caveat.
references/ files under prisma-client-api (pitfalls) + one
preview-features reference (placement: prisma-client-api or prisma-cli, maintainers'
call).undefined-in-deleteMany trap is prominent, with the strictUndefinedChecks
mitigation shown as the default recommendation.fullTextSearchPostgres, when following the skill.