Skip to content

Invalid SQL generated when related models have @deny on identical field names #2410

@lsmith77

Description

@lsmith77

Description and expected behavior

When a parent model and a related child model both have @deny access control rules on the same field name, updating the parent model generates invalid SQL with a missing FROM-clause entry.

Expected behavior: Access control rules should work correctly when the same field is protected in related models, or the PolicyPlugin should generate a clear error message explaining the limitation.

Steps to reproduce:

  1. Create two related models where both have @deny rules on a field with the same name:
model Thread {
  id                   Int      @id @default(autoincrement())
  api_key_id           Int      @deny('all', auth().role != 'ADMIN')
  question_answers     Question[]
}

model Question {
  id         Int    @id @default(autoincrement())
  api_key_id Int    @deny('all', auth().role != 'ADMIN')  // Same field name
  thread_id  Int
  thread     Thread @relation(fields: [thread_id], references: [id])
}
  1. Update the parent model (Thread) via REST API or ORM query

Actual error: [DB ERROR]: error: missing FROM-clause entry for table "ParentModelName$relationName$sub"

Workaround:
Remove the @deny rule from either the parent or child model (not both). The access control on one side of the relation is sufficient. You do not need to protect the same field on both models:
Option A: Keep @deny on parent only

model Thread {
  api_key_id Int @deny('all', auth().role != 'ADMIN')
}

model Question {
  api_key_id Int  // Remove @deny from here
}

Option B: Keep @deny on child only

model Thread {
  api_key_id Int  // Remove @deny from here
}

model Question {
  api_key_id Int @deny('all', auth().role != 'ADMIN')
}

** Environment:**

  • ZenStack version: v3.3.3
  • Database type: PostgreSQL
  • Node.js version: v23.10.0
  • Package manager: npm

Additional context

  • The issue is triggered by field name overlap: when the parent and child both protect a field with the same name
  • The PolicyPlugin fails to generate valid SQL when constructing subqueries for access control verification across relations with overlapping protected field names
  • The error references a generated table alias ($sub) that doesn't exist in the FROM clause, indicating a bug in how the PolicyPlugin builds the query
  • This is a limitation/bug of the current PolicyPlugin implementation when handling shared field names across related models

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions