Repository navigation
docs(search): name the empty-search-set refusal on the pages that describe the data read route's search - #24361
Conversation
…ages describe search A non-blank search over an object whose resolved search set is empty is refused 400 INVALID_FIELD by the engine (expandSearchOnAst), on find, findOne, count and aggregate. Six hand-written pages described search without it: error-handling's read-axis parenthesis, data-api's search row, request/result table and bullet, queries' Full-Text Search, query-syntax's internal-caller sentence, schema-design's Global search, and views' toolbar-search runtime table. Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
Re-wrap the two edits so error-handling's parenthesis and query-syntax's paragraph change only the lines that carry the new text. Claude-Session: https://claude.ai/code/session_01FM29ZqLTrnPNXxijioZwMp Co-authored-by: Claude <noreply@anthropic.com>
…arch-empty-set-docs-family
席位核对ACCEPT · Form. Draft, base Scope. 6 files, +21 / −8. The card's four pages carry +16 / −6 (budget +16). The two others, Each claim, against the code on
Gates, pinned to head Accepted deviations. Out of scope. The Acceptance notes name one docs drift in Landing. Ready, then auto-merge through the queue, by this seat. Generated by Claude Code |
Fixes #24355
Clause-②: no
What
This PR adds the empty-search-set refusal to every hand-written page that describes the data read route's
searchand did not mention it yet. Sinceec749fbb44(PR #24320), a non-blanksearchover an object whose search set comes out empty is refused with400 INVALID_FIELDinstead of answering every row. Until now these pages described field resolution only.content/docs/protocol/kernel/error-handling.mdxINVALID_FIELD, the read-axis parenthesis in the catalog pointersearchadded besidesearchFieldscontent/docs/api/data-api.mdxGET /data/:objectparameter table,searchrow400 INVALID_FIELD, never every row?search=alphaon an object with no searchable field gives400 INVALID_FIELDsearchFieldsbullet under that tablesearchandsearchFields. The bullet calledsearchFields"the only parameter whose failure changed which rows came back", and the new row would make that untrue. One sentence says what a baresearchused to docontent/docs/data-modeling/queries.mdxcontent/docs/protocol/objectql/query-syntax.mdxfind/findOne/count/aggregate(param: 'search')content/docs/data-modeling/schema-design.mdxcontent/docs/ui/views.mdx400 INVALID_FIELDwhen that set is empty"No new section.
content/docs/references/**,content/docs/releases/**andcontent/docs/api/error-catalog.mdxare untouched.The producer, read from the code (base
e4bcced0b4)emptySearchSetErrorand its single call site,ObjectQL.expandSearchOnAst(packages/objectql/src/engine.ts). It throws when the term is non-blank (normalizeSearch(raw).query.trim()) andexpandSearchToFilterreturnednull. The thrown error carriesstatus/httpStatus400,code: 'INVALID_FIELD',objectandparam: 'search'. It has nofield.resolveSearchFieldResolution(packages/spec/src/data/search-fields.ts). A declared entry counts when it names a field that exists and is not virtual (formula). If no entry counts, the auto-default applies: text / email / phone / url / autonumber / textarea / markdown / select, minus hidden and system columns.internal: truefields are removed from the map before resolution.findandfindOnecallexpandSearchOnAstdirectly;countandaggregatereach it throughexpandSearchOnOptions. All four live in the engine, so a caller ofengine.find()meets the refusal too. That is why query-syntax's sentence about internal callers keeping the tolerant intersection is kept and narrowed, not deleted: the tolerant half,resolveSearchFieldsdropping unknown requested names, has not changed.200. Global search (searchAll,packages/metadata-protocol/src/protocol.ts) skips an object whose set is empty before it queries. That is stated on schema-design, the only page here that describes global search.400 INVALID_FIELDand leave outparam. The flat/dataarm (theINVALID_FIELDarm inpackages/types/src/data-error-classification.ts) sendserror,code,fieldandobject, notparam. Only query-syntax, which describes the engine's thrown error, namesparam: 'search'.Sister sentence: the
### INVALID_FIELDsentence that PR #24353 adds toerror-catalog.mdx, read at its headd87f5a77ff. Each page reuses its terms: resolved search set is empty, nosearchableFieldsentry names a stored field, the default search scans none,internal: truefields never count, mirror the composed title onto a stored text field. The error-handling parenthesis says the catalog entry listssearch. That is only true once #24353 lands, so the two should land together or #24353 first.Enumeration
git grep -lE 'searchableFields|searchFields' e4bcced0b4 -- content/docs, minusreferences/andreleases/, gives 8 pages. I read each once.search?api/data-api.mdxdata-modeling/queries.mdxprotocol/kernel/error-handling.mdxINVALID_FIELDread axes)protocol/objectql/query-syntax.mdxdata-modeling/schema-design.mdx?search=apollo,$search, the auto-default fallbackui/views.mdxapi/error-catalog.mdxkernel/contracts/data-engine.mdxEngineQueryOptionstype listing and the predicate rule forfindOne, neither of which describes the routeLine budget
The card's four pages: +16 / -6, net +10 (budget +16). The two outside them: schema-design +4 / -1, views +1 / -1. All six: +21 / -8.
Verification (HEAD
d0e954f51, after mergingorigin/mainatd1f082d94)Docs-only: no package is touched, so no build closure and no package tests are owed. The gate list is the 41 commands from
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack(merge based1f082d94). Each ran with its exit code captured before any pipe:pnpm check:doc-authoring,check:doc-anchors,check:error-status-conformance,check:nul-bytesandcheck:corpus-claim-drift. Four of them ran after building@objectstack/lint...(lint, formula, sdui-parser, spec) under the verify lock (held 117 s):pnpm --filter @objectstack/spec run check:docs,pnpm check:docs-transcript-drift, andpnpm --filter @objectstack/lint run check:doc-formula-expressions/check:doc-security-posture.pnpm --filter @objectstack/spec run check:skill-examplesexited 3, PREREQUISITE NOT MET, becausepackages/client-react/distholds no.d.ts. Building it means a 37-package closure. Declared narrowing: none of the eight hunks is inside a fenced code block (checked per hunk), so no marked example changed. CI runs the gate.--ranreconciliation: "41 derived famil(ies) accounted for — 40 run, 1 NOT-MEASURED".Build Docsjob and the type-check lanes.Acceptance notes
ui/views.mdx, under "What the object allows": the allowed set for a declaring object is described as "that list, verbatim — whatever the field types are". In the code,resolveSearchFieldResolutiondrops entries that name no field or aformulafield. The last table row in the same section does refuse the formula case. Docs drift, not filed, no carrier.kernel/contracts/data-engine.mdx: theEngineQueryOptionscomment forsearchdoes not mention the refusal. The engine-caller statement is on query-syntax. Read and left (see above).Generated by Claude Code