diff --git a/packages/plugins/policy/src/policy-handler.ts b/packages/plugins/policy/src/policy-handler.ts index f42459bc4..968703957 100644 --- a/packages/plugins/policy/src/policy-handler.ts +++ b/packages/plugins/policy/src/policy-handler.ts @@ -920,6 +920,10 @@ export class PolicyHandler extends OperationNodeTransf for (let i = 0; i < data.length; i++) { const item = data[i]!; if (typeof item === 'object' && item && 'kind' in item) { + if (item.kind === 'DefaultInsertValueNode') { + result.push({ node: ValueNode.create(null), raw: null }); + continue; + } const fieldDef = QueryUtils.requireField(this.client.$schema, model, fields[i]!); invariant(item.kind === 'ValueNode', 'expecting a ValueNode'); result.push({ diff --git a/tests/regression/test/issue-2460.test.ts b/tests/regression/test/issue-2460.test.ts new file mode 100644 index 000000000..2ad48a147 --- /dev/null +++ b/tests/regression/test/issue-2460.test.ts @@ -0,0 +1,37 @@ +import { createPolicyTestClient } from '@zenstackhq/testtools'; +import { describe, expect, it } from 'vitest'; + +// createManyAndReturn fails with "Invariant failed: expecting a ValueNode" +// when rows in the batch have asymmetric columns (one row provides a field the other omits) +describe('Regression for issue #2460', () => { + it('createManyAndReturn with asymmetric optional fields across rows', async () => { + const db = await createPolicyTestClient( + ` +model User { + id Int @id @default(autoincrement()) + role String + @@allow('all', true) +} + +model Item { + id Int @id @default(autoincrement()) + key String + note String? + @@allow('all', auth().role == 'admin') +} + `, + { provider: 'postgresql' }, + ); + + const user = await db.user.create({ data: { role: 'admin' } }); + + const result = await db.$setAuth(user).item.createManyAndReturn({ + data: [ + { key: 'a', note: 'hello' }, + { key: 'b' }, + ], + }); + + expect(result).toHaveLength(2); + }); +});