DataFn
Server

Validation

Request validation and schema compliance checks.

Overview

Every query and mutation is validated against the schema before execution. Validation catches structural errors, unknown fields, limit violations, and prototype pollution attempts. Errors are returned as structured objects with a code, message, and path pointing to the invalid location.

Query Validation

The following checks are applied to every query:

CheckDescription
Resource existsThe resource field must reference a resource defined in the schema.
Field names validFields in select, filters, sort, groupBy, having, and search.fields must exist in the schema.
Relation names validRelation tokens in select and filters must reference defined relations.
Select tokens parseableEach token in select is parsed and validated (e.g., "assignee.*", "tags.#").
Filter depth boundedFilter nesting depth is capped at 10 levels.
Relation depth boundedRelation expansion depth in select tokens is capped at 5 levels.
Prototype pollutionFilter objects are checked for disallowed keys (__proto__, constructor, prototype).

Query Limits

LimitDefaultConfig KeyDescription
Max select tokens50maxSelectTokensMaximum number of tokens in a select array.
Max filter keys per level20maxFilterKeysPerLevelMaximum number of keys at each filter nesting level.
Max sort fields10maxSortFieldsMaximum number of fields in a sort array.
Max aggregations20maxAggregationsMaximum number of aggregation definitions.
Max LIKE pattern length200--Maximum character length for $like and $ilike patterns.
Max search query length1000--Maximum character length for search.query.

When a limit is exceeded, the server returns a DFQL_INVALID or LIMIT_EXCEEDED error:

{
  "ok": false,
  "error": {
    "code": "DFQL_INVALID",
    "message": "Select exceeds limit: 55 tokens (max 50)",
    "details": { "path": "select" }
  }
}

Cursor Validation

When cursor-based pagination is used (cursor.after or cursor.before), the query must include a sort with id as the last tie-breaker field. If sort is absent, it defaults to ["id:asc"].

Mutation Validation

The following checks are applied to every mutation:

CheckDescription
Mutation is objectThe body must be a plain object (not array, null, or primitive).
Resource existsThe resource field must reference a defined resource.
Operation validMust be one of: insert, merge, replace, delete, relate, modifyRelation, unrelate.
ID is stringThe id field must be a string within maxIdLength (default: 255).
ID prefix matchesIf the resource defines idPrefix, the ID must start with that prefix.
Record keys match schemaFor insert, merge, and replace, all keys in record must be recognized fields or relations.
Required fields presentFor insert and replace, required fields without defaults must be present.
Field types validField values are validated against their declared types in the schema.
Relation names validFor relate, modifyRelation, unrelate, the relations object keys must reference defined relations.
Guard filter validThe optional if guard object keys must reference readable fields.
clientId / mutationIdIf present, must be non-empty strings of at most 255 characters.
versionIf present, must be a positive integer.
Prototype pollutionThe entire mutation object is checked for disallowed keys.

Mutation Limits

LimitDefaultConfig KeyDescription
Max ID length255maxIdLengthMaximum character length for the id field.
Max transact steps100maxTransactStepsMaximum steps in a /datafn/transact request.
Max payload bytes5,242,880maxPayloadBytesMaximum request body size.

Batch Validation

Both query and mutation endpoints accept batch requests (JSON arrays). Each item in the batch is validated independently. On failure, the error includes an index property identifying which item failed:

{
  "ok": false,
  "error": {
    "code": "DFQL_UNKNOWN_RESOURCE",
    "message": "Unknown resource: nonexistent",
    "details": { "path": "$[2].resource", "index": 2 }
  }
}

Push Validation

The /datafn/push endpoint validates all mutations in the mutations array and collects all errors (non-fail-fast). This allows clients to see every validation issue in a single response rather than fixing them one at a time.

Prototype Pollution Protection

All filter objects, mutation bodies, and record objects are scanned for keys that could trigger prototype pollution:

  • __proto__
  • constructor
  • prototype

If any of these keys are detected, the request is rejected with DFQL_INVALID:

{
  "ok": false,
  "error": {
    "code": "DFQL_INVALID",
    "message": "Disallowed key: __proto__",
    "details": { "path": "filters" }
  }
}

Error Codes

CodeHTTP StatusDescription
DFQL_INVALID400Structural error in the request body.
DFQL_UNKNOWN_RESOURCE400The referenced resource does not exist in the schema.
DFQL_UNKNOWN_FIELD400A field name is not recognized for the resource.
DFQL_UNKNOWN_RELATION400A relation name is not recognized for the resource.
DFQL_UNSUPPORTED400The request uses an unsupported feature (e.g., filters.$or).
LIMIT_EXCEEDED400A configured limit was exceeded.
FORBIDDEN403Authorization denied.