> For the complete documentation index, see [llms.txt](https://bxorm.ortusbooks.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://bxorm.ortusbooks.com/bxorm-2.x/working-with-entities/criteria.md).

# Criteria Queries

Build queries fluently with entityCriteria(): conditions, joins, projections, paging and bulk statements

`entityCriteria()` builds a query one method at a time. You chain conditions, joins, projections and ordering, then run it with a terminal method such as `list()`, `count()`, `get()` or `paginate()`. There is no query string to write, property names are checked as you go, and values are always bound as parameters.

```js
users = entityCriteria( "User" )
    .isEq( "active", true )
    .like( "lastName", "Sm%" )
    .order( "lastName" )
    .list();
```

## How it works

* **Building methods** add to the criteria and return it, so they chain.
* **Terminal methods** run the query and return the result. They never change the criteria, so one criteria can run several queries (`count()` then `list()`, for example).
* `copy()` gives you an independent copy to branch from.
* Method names are case-insensitive and accept positional or named arguments: `isEq( "make", "Ford" )` or `isEq( property = "make", value = "Ford" )`.
* Property names are checked when you add them. A typo fails at once with a suggestion: `Vehicle has no property [mkae]. Did you mean [make]?`

```js
c = entityCriteria( "Vehicle" ).isEq( "make", "Honda" );
total = c.count();
page  = c.order( "model" ).maxResults( 10 ).list();
```

## Conditions

Every condition is added with `and`. Values are bound as parameters and converted to the property's type, so `isEq( "id", "42" )` works for a numeric id.

| Method (aliases)                                                                               | Meaning                                                                                      |
| ---------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
| `isEq( p, v )` (`eq`)                                                                          | `p = v`; a `null` value means `p is null`                                                    |
| `ne( p, v )` (`isNe`)                                                                          | `p <> v`; a `null` value means `p is not null`                                               |
| `isGt` (`gt`), `isGe` (`ge`, `gte`), `isLt` (`lt`), `isLe` (`le`, `lte`)                       | Comparisons                                                                                  |
| `like( p, pattern )`                                                                           | `p like pattern` (you include the `%` wildcards)                                             |
| `ilike( p, pattern )`                                                                          | `like`, ignoring case                                                                        |
| `between( p, min, max )`                                                                       | Inclusive range                                                                              |
| `isIn( p, values )` (`in`, `whereIn`)                                                          | `values` is an array, a comma-separated list, or a subquery. An empty list matches nothing   |
| `isNotIn( p, values )`                                                                         | The opposite of `isIn`                                                                       |
| `isNull( p )`, `isNotNull( p )`                                                                | Null checks                                                                                  |
| `isTrue( p )`, `isFalse( p )`                                                                  | Boolean properties                                                                           |
| `isEmpty( p )`, `isNotEmpty( p )`                                                              | Collections (one-to-many, many-to-many)                                                      |
| `sizeEq`, `sizeNe`, `sizeGt`, `sizeGe`, `sizeLt`, `sizeLe( p, n )`                             | Collection size                                                                              |
| `eqProperty`, `neProperty`, `gtProperty`, `geProperty`, `ltProperty`, `leProperty( p, other )` | Compare two properties                                                                       |
| `idEq( id )`                                                                                   | Match the id. For a composite id pass a struct: `idEq( { make : "Ford", model : "F-150" } )` |
| `sql( fragment, params )` (`sqlRestriction`)                                                   | A native SQL condition, see below                                                            |

### `where()` shorthands

```js
c.where( "make", "Honda" );              // isEq
c.where( "price", ">=", 20000 );         // =, !=, >, >=, <, <=, like, ilike, in, not in
c.where( { make : "Honda", year : 2024 } ); // several isEq; a null value means is null
c.where( ( c ) => c.isEq( "a", 1 ).isEq( "b", 2 ) ); // an and-group
```

### Groups: `anyOf()` and `allOf()`

`anyOf()` joins the conditions of its closure with `or`. `allOf()` joins them with `and`, which is useful inside `anyOf()`.

```js
// make = Honda OR make = Toyota
entityCriteria( "Vehicle" ).anyOf( ( c ) => c.isEq( "make", "Honda" ).isEq( "make", "Toyota" ) );

// (make = Honda AND model like R%) OR year < 2000
entityCriteria( "Vehicle" ).anyOf( ( c ) => c
    .allOf( ( a ) => a.isEq( "make", "Honda" ).like( "model", "R%" ) )
    .isLt( "year", 2000 )
);
```

Several closures passed to `anyOf()` are alternatives, and each closure's own conditions must all match:

```js
entityCriteria( "Vehicle" ).anyOf(
    ( c ) => c.isEq( "make", "Honda" ).isEq( "model", "Civic" ),
    ( c ) => c.isEq( "make", "Ford" )
);
```

Aliases: `$or`, `or`, `orWhere`, `disjunction` for `anyOf`; `$and`, `and`, `conjunction` for `allOf`.

### Negation

`not( closure )` negates a group. Any condition can also be negated with the `not` prefix: `notLike`, `notIn`, `notBetween`, `notEq`, `notEmpty`, ...

```js
entityCriteria( "Vehicle" ).notLike( "make", "Hon%" );
entityCriteria( "Vehicle" ).not( ( c ) => c.isEq( "make", "Honda" ).isEq( "model", "Civic" ) );
```

### Restrictions: `c.restrictions`

`c.restrictions` builds a condition without adding it, the cborm way. Pass the results to `add()`, `or()`, `and()` or `not()`. Every condition method is there, under the same names and aliases, including the `not...` forms, plus `or`, `and` and `not` to nest them. Restrictions and closures can be mixed.

```js
c = entityCriteria( "User" );
r = c.restrictions;

c.or( r.isEq( "role", "admin" ), r.isGt( "age", 30 ) );
c.add( r.like( "name", "A%" ), r.isNotNull( "email" ) );
c.not( r.isEq( "status", "banned" ) );
c.add( r.or( r.isEq( "a", 1 ), r.and( r.isEq( "b", 2 ), r.not( r.isNull( "c" ) ) ) ) );
c.or( r.isEq( "a", 1 ), ( c ) => c.isEq( "b", 2 ) );
```

A restriction is resolved against the criteria it is added to. Calling a method that is not a condition (for example `c.restrictions.list()`) is an `orm.argument` error.

### Native SQL: `sql()`

`sql( fragment, params )` adds a SQL condition. `?` takes the params in order (always bound). `{alias}.column` refers to a column of the entity, and `{property}` (or `{association.property}`) to a property.

```js
c.sql( "upper({alias}.first_name) = ?", [ "LUIS" ] );
c.sql( "lower({make}) = ? or {model} = ?", [ "ford", "Civic" ] );
```

## Associations and joins

A dotted path joins its associations automatically:

```js
entityCriteria( "Vehicle" ).isEq( "manufacturer.name", "Ford Motor Company" );
```

* A condition uses an **inner** join, so rows without the association are left out.
* Inside `anyOf()` and `not()` a **left** join is used, so a row without the association can still match another branch.
* Ordering and projections use a **left** join, so ordering never drops rows.
* The same path is joined once and reused.
* `manufacturer.id` compares the foreign key and needs no join.
* An association can be compared with an id or an entity: `isEq( "manufacturer", 42 )`, `isIn( "manufacturer", [ 1, 42 ] )`.

The root entity's alias is `this` (`this.name`).

### Aliases and join types

```js
entityCriteria( "Vehicle" )
    .joinTo( "manufacturer", "m" )          // alias createAlias; optional third argument: join type
    .isEq( "m.name", "Honda Motor Co." );

c.leftJoin( "manufacturer", "m" );          // also innerJoin, rightJoin, fullJoin
c.joinTo( "manufacturer", "m", "left" );    // inner, left, right, full, or c.LEFT_JOIN (cborm constants)
```

Right and full joins need database support (MySQL and MariaDB have no full join).

### `with{Association}()`

`with{Association}()` makes an association the start of unqualified paths. With a closure it applies to the closure's conditions; without one it applies until `end()`. `createCriteria( association )` is the cborm form.

```js
entityCriteria( "Vehicle" )
    .withManufacturer( ( m ) => m.like( "name", "Honda%" ) )
    .isEq( "model", "Civic" );

entityCriteria( "Vehicle" )
    .withManufacturer( "left" )
        .like( "name", "Honda%" )
    .end()
    .isEq( "model", "Civic" );
```

### Fetching

`fetch( association )` loads an association together with the root rows, so reading it later needs no extra query:

```js
vehicles = entityCriteria( "Vehicle" ).fetch( "manufacturer" ).list();
```

When a condition goes through a to-many association, each root entity is returned once, and `count()` counts each root once.

## Functions in paths

Any property argument can be a function call: in conditions, in `order()`, in `pluck()` and in projections.

```js
entityCriteria( "Order" ).isEq( "year(createdDate)", 2025 );
entityCriteria( "Manufacturer" ).isEq( "lower(name)", "ford motor company" );
entityCriteria( "Manufacturer" ).isEq( "upper(substring(name, 1, 4))", "FORD" );   // nested calls and number literals
entityCriteria( "Manufacturer" ).isEq( "coalesce(address, 'none')", "none" );       // 'quoted strings'
entityCriteria( "Manufacturer" ).isEq( "cast(id as String)", "42" );
entityCriteria( "Vehicle" ).isEq( "lower(manufacturer.name)", "honda motor co." );  // paths join as usual
entityCriteria( "Manufacturer" ).order( "length(name) desc" );
entityCriteria( "Manufacturer" ).pluck( "upper(name)" );
```

* Each argument must be a property path, a nested function call, a number or a `'quoted string'` (`''` escapes a quote). Anything else is an `orm.argument` error: pass other values as the condition value, where they are bound as parameters.
* The function can be an HQL function (`lower`, `upper`, `length`, `substring`, `coalesce`, `year`, `cast`, ...), a function of the database dialect, or one of the application's [named SQL functions](/bxorm-2.x/getting-started/configuration.md#named-sql-functions).
* Property names inside the call are checked like any other path (`lower(nmae)` is an `orm.property.unknown` error with a suggestion).
* An unknown function name is passed to the database, which rejects it when the query runs (`orm.sql`).

## Subqueries

`subquery( entityName, alias )` creates a subquery. Inside it, unqualified paths start at the subquery's entity, and `this.` refers to the outer query's root.

```js
c = entityCriteria( "Manufacturer" );

// manufacturers that make a Honda
c.exists( c.subquery( "Vehicle", "v" ).eqProperty( "v.manufacturer", "this" ).isEq( "make", "Honda" ) );

// manufacturers with no vehicles
c.notExists( c.subquery( "Vehicle", "v" ).eqProperty( "v.manufacturer", "this" ) );

// isIn with the subquery's projection
c.isIn( "id", c.subquery( "Vehicle", "v" ).isEq( "make", "Ford" ).project( ( p ) => p.property( "manufacturer.id" ) ) );
```

The cborm forms are available too: `propertyEq`, `propertyNe`, `propertyGt`, `propertyGe`, `propertyLt`, `propertyLe`, `propertyIn`, `propertyNotIn` compare a property with a subquery, and `subEq`, `subNe`, `subGt`, `subGe`, `subLt`, `subLe`, `subIn`, `subNotIn` compare a value with one:

```js
counted = c.subquery( "Vehicle", "v" ).eqProperty( "v.manufacturer", "this" ).project( ( p ) => p.rowCount() );
c.subLe( 2, counted );   // manufacturers with at least 2 vehicles
```

Quantified forms compare with every row (`All`) or at least one row (`Some`) of the subquery, e.g. `x >= all (select ...)`. The cborm set:

| Compare a property                    | Compare a value               |
| ------------------------------------- | ----------------------------- |
| `propertyEqAll( property, subquery )` | `subEqAll( value, subquery )` |
| `propertyGtAll`, `propertyGtSome`     | `subGtAll`, `subGtSome`       |
| `propertyGeAll`, `propertyGeSome`     | `subGeAll`, `subGeSome`       |
| `propertyLtAll`, `propertyLtSome`     | `subLtAll`, `subLtSome`       |
| `propertyLeAll`, `propertyLeSome`     | `subLeAll`, `subLeSome`       |

```js
prices = c.subquery( "Product", "p" ).isEq( "p.category", "books" ).project( ( p ) => p.property( "price" ) );
c.propertyGeAll( "price", prices );   // at least as expensive as every book
c.subLtSome( 10, prices );            // some book costs more than 10
```

## Results

### Projections

`project()` selects columns instead of entities. Each method takes a property and an optional alias:

```js
entityCriteria( "Vehicle" )
    .project( ( p ) => p.group( "make" ).count( "vin", "total" ).avg( "price" ) )
    .asStruct()
    .list();
// [ { make : "Ford", total : 1, price : ... }, ... ]
```

Methods: `property`, `group` (`groupProperty`), `sum`, `avg`, `min`, `max`, `count`, `countDistinct`, `rowCount( [alias] )`, `id( [alias] )`. An alias defaults to the property name.

The cborm form, `withProjections()`, takes a struct or named arguments whose values are `property[:alias]` lists:

```js
c.withProjections( groupProperty = "make", count = "vin:total", distinct = "model" );
```

With one projection, `list()` returns plain values; with several, one array per row, or one struct per row with `asStruct()`.

### Result shapes

| Method                            | `list()` returns                                                                                           |
| --------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| (default)                         | Entities                                                                                                   |
| `asStruct()`                      | One struct per row. Without projections: the id and plain properties. Date values are ISO 8601 strings     |
| `asStruct( includes, [options] )` | Structs built like `entityToStruct()`, read with projection queries instead of loading entities. See below |
| `asQuery()`                       | A query                                                                                                    |
| `asStream()`                      | A Java stream                                                                                              |
| `asDistinct()`                    | Distinct rows                                                                                              |

### Structs with includes

`asStruct( includes, [options] )` returns the structs [`entityToStruct()`](/bxorm-2.x/working-with-entities/structs.md) would build, without loading any entity: the criteria's conditions and order select the rows, one projection query reads the plain values and to-one associations, and each to-many association is one more query. The entity's `this.memento`, excludes, mappers, defaults and profiles apply; options are `excludes`, `mappers`, `defaults`, `ignoreDefaults` and `profile`.

```js
users = entityCriteria( "User" )
    .isEq( "active", true )
    .order( "lastName" )
    .asStruct( "id,lastName,role.name,orders", { excludes : "orders.notes" } )
    .paginate( page = 1, maxRows = 25 );
```

It works with `list()`, `get()`, `first()` and `paginate()`. With `each()` or `chunk()` it is an `orm.argument` error. See [Entities as Structs](/bxorm-2.x/working-with-entities/structs.md) for the rules.

### Ordering and paging

```js
c.order( "lastName" );                    // asc by default
c.order( "lastName", "desc" );
c.order( "lastName", "asc", true );       // ignore case (text properties)
c.orderBy( "make desc, model asc" );
c.orderByDesc( "createdDate" );
c.firstResult( 20 ).maxResults( 10 );     // aliases: offset, limit
```

Without an `order()`, `list()`, `get()`, `first()` and `paginate()` return entity rows in the entity's [`defaultSort`](/bxorm-2.x/modeling/entities.md#default-sort-order) order, when it declares one. An explicit `order()` replaces it, and it is not used for counts or projections.

### Options

| Method                     | Effect                                                                                                            |
| -------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `cache( [region] )`        | Cache the result in the second-level query cache (needs `secondaryCacheEnabled`); `cache( false )` to turn it off |
| `readOnly()`               | Loaded entities are read-only: their changes are not saved                                                        |
| `timeout( seconds )`       | Query timeout                                                                                                     |
| `fetchSize( n )`           | JDBC fetch size                                                                                                   |
| `comment( text )`          | SQL comment (shown with `logSQL` in the ORM settings)                                                             |
| `queryHint( name, value )` | A Hibernate query hint                                                                                            |

## Terminal methods

| Method                                     | Returns                                                                                                                                   |
| ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `list()`                                   | The rows. cborm arguments work too: `list( max, offset, timeout, sortOrder, ignoreCase, asQuery )`                                        |
| `count( [property] )`                      | The number of matching entities, or of distinct values of a property                                                                      |
| `exists()`                                 | Whether any row matches                                                                                                                   |
| `get( [uniqueFirst] )`                     | The single match, or null. More than one match is an `orm.query.nonUnique` error unless `uniqueFirst` is true                             |
| `getOrFail( [uniqueFirst] )`               | Like `get()`, but no match is an `orm.notFound` error                                                                                     |
| `first()`                                  | The first row in order, or null                                                                                                           |
| `firstOrFail()`                            | Like `first()`, but no row is an `orm.notFound` error                                                                                     |
| `paginate( page = 1, maxRows = 25 )`       | `{ results, pagination : { page, maxRows, offset, totalRecords, totalPages } }`                                                           |
| `simplePaginate( page = 1, maxRows = 25 )` | `{ results, pagination : { page, maxRows, hasMore } }`, without counting                                                                  |
| `pluck( property )`                        | One property's values, in order                                                                                                           |
| `sum`, `avg`, `min`, `max( property )`     | An aggregate                                                                                                                              |
| `each( callback, [size] )`                 | Calls the closure once per row; returns the row count                                                                                     |
| `chunk( size, callback )`                  | Calls the closure with each batch of rows; returns the row count                                                                          |
| `updateAll( values )`                      | Sets properties on every matching row with one `UPDATE`; returns the row count. See [Bulk updates and deletes](#bulk-updates-and-deletes) |
| `deleteAll()`                              | Deletes every matching row with one `DELETE`; returns the row count. See [Bulk updates and deletes](#bulk-updates-and-deletes)            |

`each()` and `chunk()` read the rows in batches (100 by default for `each()`). After each batch the session is flushed, so changes made in the callback are saved, and cleared, so memory stays flat. Without an explicit order, batches follow the id (not the entity's `defaultSort`), so deleting or changing rows in the callback never skips any.

```js
entityCriteria( "User" ).isFalse( "verified" ).chunk( 500, ( users ) => {
    users.each( ( u ) => u.setReminderSent( true ) );
} );
```

## Bulk updates and deletes

`updateAll()` and `deleteAll()` change every matching row with a single HQL statement, without loading any entity. Both return the number of rows changed.

```js
// one UPDATE
count = entityCriteria( "Order" )
    .isEq( "status", "pending" )
    .isLt( "createdDate", dateAdd( "d", -30, now() ) )
    .updateAll( { status : "expired", note : null } );

// one DELETE
count = entityCriteria( "Session" ).isLt( "expires", now() ).deleteAll();
```

`updateAll()` takes a struct of property values. It can set plain properties and to-one associations (pass an entity or an id), and `null` values are allowed. Collections cannot be set.

`deleteAll()` on a [`softDelete`](/bxorm-2.x/modeling/entities.md#soft-delete) entity marks the rows deleted instead of removing them.

Conditions through an association (`isEq( "manufacturer.name", "Ford" )`) are turned into an id subquery, which needs an entity with a single id.

{% hint style="warning" %}
Bulk statements run in the database only:

* No entity events fire.
* No cascades: child rows are not deleted, so foreign keys can reject a `deleteAll()`.
* No version increments and no [`autoTimestamp`](/bxorm-2.x/modeling/properties.md#automatic-timestamps) values.
* Entities already loaded in the session keep their old values. Reload them (`entityReload()`) or clear the session (`ormClearSession()`) to see the change.

Pending changes in the session are flushed before the statement runs.
{% endhint %}

## Locking rows

`lock( [mode], [options] )` locks the rows that `list()`, `get()` and `first()` return, until the transaction ends. Counts and aggregates are not locked. The mode is `write` (the default, exclusive), `read` (shared) or `force` (exclusive, and increments the version); see [entityLock()](/bxorm-2.x/reference/built-in-functions/entitylock.md). Options are `timeout` (seconds to wait; `0` means do not wait) and `skipLocked`.

A queue worker that claims up to 10 new jobs, skipping jobs another worker has already locked:

```js
transaction {
    jobs = entityCriteria( "Job" )
        .isEq( "status", "new" )
        .lock( "write", { skipLocked : true } )
        .maxResults( 10 )
        .list();
    jobs.each( ( job ) => job.setStatus( "running" ) );
}
```

`lock()` must run inside `transaction{}`, otherwise an `orm.argument` error is raised.

## Flow helpers

```js
entityCriteria( "User" )
    .when( len( search ), ( c ) => c.like( "lastName", search & "%" ) )
    .when( role == "admin", ( c ) => c.isTrue( "isAdmin" ), ( c ) => c.isFalse( "isAdmin" ) )
    .unless( showDeleted, ( c ) => c.isFalse( "isDeleted" ) )
    .apply( activeUsers )        // a reusable closure: activeUsers = ( c ) => c.isTrue( "active" )
    .peek( ( c ) => writeLog( c.count() ) )
    .list();
```

## Seeing the query

| Method                                                               | What it does                                                                                                                                                                         |
| -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `getSQL( [executable], [format] )`                                   | The SQL Hibernate would run, without running it. `executable = true` puts the values in (for pasting into a SQL tool); `format = false` keeps it on one line. Paging is not included |
| `peekSQL( callback )`                                                | Calls the closure with the SQL and keeps chaining                                                                                                                                    |
| `logSQL( [label], [executable], [format] )`                          | Appends `{ type : label, sql }` to the SQL log, writes the SQL to the ORM log, and keeps chaining. The label defaults to `Criteria`                                                  |
| `getSqlLog()`                                                        | The SQL log entries, oldest first                                                                                                                                                    |
| `startSqlLog( [returnExecutableSql], [formatSql] )` / `stopSqlLog()` | Turn the SQL log on and off (cborm). `startSqlLog()` also sets how later `logSQL()` calls write the SQL; both default to `false`                                                     |
| `canLogSql()` / `getSqlLoggerActive()`                               | Whether `startSqlLog()` turned the log on                                                                                                                                            |
| `getHQL()`                                                           | The HQL the criteria compiles to                                                                                                                                                     |
| `toString()` / `writeDump()`                                         | The calls you made, the HQL, the parameters and the SQL                                                                                                                              |

```js
writeDump( entityCriteria( "Vehicle" ).isEq( "make", "Honda" ).like( "manufacturer.name", "Honda%" ) );
// entityCriteria( "Vehicle" )
//     .isEq( "make", "Honda" )
//     .like( "manufacturer.name", "Honda%" )
// HQL: select bx_this from Vehicle bx_this inner join bx_this.manufacturer bx_j1 where (bx_this.make = ?1 and bx_j1.name like ?2)
// Params: ["Honda", "Honda%"]
// SQL: select ...
```

```js
c = entityCriteria( "Vehicle" ).startSqlLog( returnExecutableSql = true );
c.isEq( "make", "Honda" ).logSQL( "hondas" );
c.like( "model", "C%" ).logSQL( "civics" );
writeDump( c.getSqlLog() );   // [ { type : "hondas", sql : "..." }, { type : "civics", sql : "..." } ]
```

`copy()` copies the log. Nothing is logged on its own: call `logSQL()` where you want an entry.

`getSQL()` needs bx-orm's Hibernate statement inspector. If your ORM settings configure your own (`hibernate.session_factory.statement_inspector`), `getSQL()` says so.

## Interception points

The cborm criteria events are announced as BoxLang interception points. Each receives `criteriaBuilder`, and the `after` points also receive the result.

| Point                        | Extra data                    |
| ---------------------------- | ----------------------------- |
| `beforeCriteriaBuilderList`  |                               |
| `afterCriteriaBuilderList`   | `results`                     |
| `beforeCriteriaBuilderCount` |                               |
| `afterCriteriaBuilderCount`  | `count`                       |
| `beforeCriteriaBuilderGet`   |                               |
| `afterCriteriaBuilderGet`    | `result`                      |
| `onCriteriaBuilderAddition`  | `type` (the condition method) |

## Errors

| Error                  | When                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `orm.property.unknown` | A property that does not exist (including in `updateAll()`), or a path through a plain value, with a suggestion                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
| `orm.argument`         | An unknown method or argument, a bad join type, operator or sort direction, a subquery run on its own; a function path argument that is not a path, function, number or quoted string, or unbalanced parentheses; `asStruct( includes )` with `each()` or `chunk()`, with a getter-only include, a value collection or a composite-id entity; `updateAll()` with an empty struct or a collection property; `updateAll()` or `deleteAll()` with `maxResults()` or `firstResult()`, or with association conditions on a composite-id entity; `lock()` with an unknown mode or outside `transaction{}` |
| `orm.query.nonUnique`  | `get()` matched more than one row                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `orm.notFound`         | `getOrFail()` or `firstOrFail()` matched nothing                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `orm.query.parameter`  | `sql()` params do not match its `?` placeholders                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| `orm.sql`              | The database rejected the query, for example an unknown function name in a path                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |

See [Errors and Diagnostics](/bxorm-2.x/advanced/errors-and-diagnostics.md) for the full catalog.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://bxorm.ortusbooks.com/bxorm-2.x/working-with-entities/criteria.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
