INVALID_FIELD_PATH — search condition references unknown field path
cyoda-go version 0.8.4
errors.INVALID_FIELD_PATH
Section titled “errors.INVALID_FIELD_PATH”INVALID_FIELD_PATH — a condition’s jsonPath, or a sort key, is not valid JSON Path syntax, or names a field absent from the target model’s locked schema.
SYNOPSIS
Section titled “SYNOPSIS”HTTP: 400 Bad Request. Retryable: no (unless the model schema is then extended via re-import; the request is then valid against the new locked schema).
DESCRIPTION
Section titled “DESCRIPTION”Three checks emit this code.
1. Syntax. A condition’s jsonPath is JSON Path nomenclature, so the $. leader is required:
jsonPath = "$." segment ( "." segment )*segment = name subscript*name = 1*( ALPHA / DIGIT / "_" / "-" ) ; ASCII onlysubscript = "[" ( "*" / 1*DIGIT ) "]" ; the digit run must fit a signed 32-bit integer$.amount and $.address.city are paths. A bare amount is not one and is rejected — it is not a tolerated alias. So are an empty path, an empty or trailing segment ($..a, $.a.), bracket-quoted property access ($['x'], $.['x'], $.a["b"] — use dotted access instead), and any character outside the segment set.
A well-formed array subscript — the wildcard [*] or a non-negative index [0] — is valid JSON Path and is accepted ($.tags[*].name, $.arr[0], $.matrix[*][*], $.orders[*].lines[*].sku); it cannot be pushed into the storage query, so it is evaluated in memory.
Any other bracket spelling is rejected with this code: an unclosed or unmatched bracket ($.a[, $.a[0, $.a]), a subscript with no field name before it ($.[0]), an empty subscript ($.a[]), a negative or signed index ($.a[-1], $.a[+1]), a slice ($.a[0:2]), a union ($.a[0,1]), a filter expression ($.a[?(@.x)]), and whitespace inside one ($.a[ 0]). A positional index must also fit a signed 32-bit integer: 2147483647 is the largest accepted, and a wider digit run ($.a[2147483648]) is rejected with this code rather than truncated or wrapped — no entity array is long enough for such an index to address a real position. Characters after a well-formed subscript are checked too — $.a[0]b, $.a[0];DROP and $.a[*]..b are all rejected. These previously slipped through unvalidated and answered 200 with an empty page (or, on the grouped-stats condition and workflow-criterion surfaces, wrong buckets and a criterion that silently never fired).
This check is syntactic and runs on every search-shaped surface regardless of whether a schema is loaded: /search (sync and async), conditional delete, and the condition of a grouped-statistics query.
2. Schema. Before executing a search, the server validates that every data-field path referenced by the condition (e.g. $.price, $.profile.email) resolves against the target model’s locked schema. Lifecycle paths (state, previousTransition, etc.) bypass this check.
A path that is a pure container — a known structural interior with substructure (an object with child fields) but no scalar observation of its own — is also rejected this way when compared with a scalar operator: a container has no scalar value to compare against, so the client must navigate to a leaf sub-path. IS_NULL/NOT_NULL are exempt (they test presence, not a value) and remain valid on a container path. A path observed as both an object and a bare scalar across different entities is not a pure container — it is searchable via its scalar type, and the object-valued entities remain reachable through their child leaves.
A path ending in [*] addresses the array’s elements, so the same rule applies to them: an array of scalars ($.tags[*]) and an array whose elements were also observed as bare scalars are comparable, while an array of pure objects ($.items[*]) is a container — write $.items[*].sku.
If any referenced path is unknown, the server performs at most one bounded RefreshAndGet against the model store to recover from a stale cached schema. If the path is still unknown after the refresh, the request is rejected with HTTP 400 and errorCode: "INVALID_FIELD_PATH". The response detail names every offending path so clients can correct the request without round-tripping to the support team.
A condition referencing an unrecognized lifecycle/meta filter field (not one of the known state, creationDate, lastUpdateTime, transitionForLatestSave/previousTransition, transactionId, id fields) is rejected the same way, on both /search and the grouped-statistics endpoint (POST /api/entity/stats/{entityName}/{modelVersion}/query). Grouped statistics does not have data-model schema access, so it enforces this meta-field check but not the schema-backed data-field-path check described above.
Programmatic clients should branch on errorCode == "INVALID_FIELD_PATH" (not on HTTP 400) to distinguish unknown-field-path errors from other 400s such as BAD_REQUEST (malformed JSON) or CONDITION_TYPE_MISMATCH (incompatible value type).
Common causes:
- The
$.leader is missing (amountinstead of$.amount). - Bracket-quoted access (
$['amount']) instead of dotted access ($.amount). - The condition references a field that has not been declared in the model schema.
- The model has been re-imported with a different shape and the client’s condition uses an old field name.
- The path is misspelled (e.g.
$.Namevs$.name).
To resolve: write the path as JSON Path with the $. leader, then verify the field against the model’s schema (GET /api/model/.../export), or extend the model schema and re-lock it before retrying.
The same grammar applies to a grouped-statistics groupBy entry and aggregation field, but those report INVALID_GROUP_BY_PATH / INVALID_AGGREGATION_FIELD instead, and additionally reject array subscripts (a group key must be a single scalar). The reserved groupBy token state is a token, not a path, and needs no leader.
3. Sort paths. A sort key — the HTTP sort query parameter or a gRPC orderBy.path — reports this code too, and is held to the grammar above with one addition and one relaxation. It rejects array subscripts and projections (items[*].name, items[0].name), for the same reason a groupBy entry does: an ordering needs a single scalar, and a projection denotes none. Schema membership is not a substitute — a scalar leaf inside an array of objects is a recorded field. And the $. leader is optional on a sort key: price and $.price are both accepted, since a bare dotted path is the parameter’s own spelling. Sort keys are also rejected with this code when the path is absent from the locked schema, names an array field, names an unknown meta field, duplicates another key, or exceeds CYODA_SEARCH_MAX_SORT_KEYS.
SEE ALSO
Section titled “SEE ALSO”- errors
- errors.BAD_REQUEST
- errors.CONDITION_TYPE_MISMATCH
- search
See also
Section titled “See also”cyoda help errors— Every error response from the Cyoda REST API carries a structurederrorCodein thepropertiesobject. Multiple codes may share the same HTTP status. Programmatic handling keys onerrorCode, not HTTP status.cyoda help errors BAD_REQUEST— Fired when the server cannot parse or structurally process the incoming request. Common triggers include invalid JSON, unsupported format specifiers, a parameter outside its allowed range, and mutually exclusive parameters set together.cyoda help errors CONDITION_TYPE_MISMATCH— Validation is parse-based: a comparison or range operand is rejected only when it parses into none of the field’s declared DataTypes. For example"abc"against a DOUBLE field is rejected — it is not a number. A numeric-looking string against a polymorphic[INTEGER, STRING]field is accepted (it parses as STRING).cyoda help search— Search operates against a specific entity model(entityName, modelVersion). Two modes are supported:
Raw formats
Section titled “Raw formats”/help/errors/invalid_field_path.json— full descriptor (matchesGET /help/{topic}envelope)/help/errors/invalid_field_path.md— body only