From 8012d0c7ab31a3606e4035880141c2bba36e5104 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 29 Oct 2026 13:17:41 +0000 Subject: [PATCH] =?UTF-8?q?docs(objectql):=20query-syntax=20=C2=A79=20stat?= =?UTF-8?q?es=20the=20all-unknown=20projection=20refusal,=20not=20the=20re?= =?UTF-8?q?tired=20every-column=20fallback?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An unknown plain column is dropped only while one requested column is known; a projection whose every entry is unknown is refused by find() / findOne() with 400 VALIDATION_ERROR, the fields: [] refusal; expand sub-reads always name id; the REST ingress answers 400 INVALID_FIELD. Claude-Session: https://claude.ai/code/session_01QSeKYp3oFeDem8Tbh8pzWA Co-authored-by: Claude --- .../docs/protocol/objectql/query-syntax.mdx | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/content/docs/protocol/objectql/query-syntax.mdx b/content/docs/protocol/objectql/query-syntax.mdx index ed169b6e2b9..5adedde25d1 100644 --- a/content/docs/protocol/objectql/query-syntax.mdx +++ b/content/docs/protocol/objectql/query-syntax.mdx @@ -1484,26 +1484,36 @@ const sorted = monthlyRevenue.sort((a, b) => ## 9. Error Handling -### Unknown Fields Are Tolerated +### Unknown Projection Fields -Unknown field **names** are not rejected by `engine.find()` — a projected field that -doesn't exist on the object is **silently dropped** (matching OData / `SELECT *` -tolerance), so a stale field reference never fails the whole query: +On a registered object, `engine.find()` and `findOne()` drop an unknown plain column from +`fields` **only while at least one requested column is known**: the unknown name is +silently omitted from each row, so a stale field reference in a mixed projection does +not fail the whole query. `id`, `created_at` and `updated_at` always count as known. ```typescript const rows = await engine.find('customer', { fields: ['name', 'nonexistent'], // `nonexistent` is not on the schema }); // Returns each row with `name`; `nonexistent` is omitted — no error thrown. + +await engine.find('customer', { fields: ['nonexistent'] }); +// Throws 400 VALIDATION_ERROR: no requested column is a field of 'customer'. ``` +A projection whose **every** entry is unknown is refused: `find()` / `findOne()` throw +`400 VALIDATION_ERROR` naming the requested columns, before any driver is asked. It is +the same refusal `fields: []` gets, because a projection the tolerance empties is an +empty projection, and an empty projection is never read as every column. + -This tolerance does **not** extend to the REST/protocol ingress: a `select` / `fields` -naming a column the object does not have is `400 INVALID_FIELD` there, because dropping -it silently answered a *narrower* projection with a *wider* one — a projection left with -no known field falls all the way back to every field. The engine's tolerance guards -internal callers (hooks, flows, expand sub-reads, registry-less hosts) that never pass -through that ingress. +`expand` sub-reads are unaffected: the engine always adds `id` to a sub-read's +projection (and strips it from the expanded record when you did not ask for it), so a +sub-read never reaches the all-unknown refusal. + +The REST/protocol ingress tolerates no unknown name at all: a `select` / `fields` +naming any column the object does not have, alone or next to known ones, is +`400 INVALID_FIELD` there. ### Security Violations