# Value expressions

Everywhere a value is needed in a *Script* (a URL, a request body, a field value, a condition, a filter value, a target id, and so on) takes one of the three forms below. There are exactly two exceptions: [the `pattern` of `Regex`](/api/reference/script/statements.md#regex) and [the `key` of `Cache`](/api/reference/script/statements.md#cache) are written as literals only, and a `{ /pointer }` inside them is not turned into a value. This document explains those three forms, where values come from (the context roots), and the locale-map rules specific to WEEGLOO data. Every field in the [Statement catalog](/api/reference/script/statements.md) follows these rules.

## The three forms {#three-forms}

| Form | Rule | Example |
|---|---|---|
| Reference | Resolves a `{ /json-pointer }` inside a string against the context. | `"{ /payload/fields/title }"` |
| Literal | A value with no `{ /ptr }` (a string, number, boolean, object, or array). Used as-is. | `"draft"`, `42`, `true`, `{ "a": 1 }` |
| Operations and conditions (JsonLogic) | An object whose single key is an operator. Its operands are themselves value expressions (references, literals, or nested operations). Depending on the slot, the operator needs a `$`. | `{ "$+": [ "{ /vars/n }", 1 ] }` |

The three forms **nest**: you put a reference in a JsonLogic operand, then feed that reference's result back into another operation.

### Data slots and expression slots: when to prefix with $ {#dollar-prefix}

The same JSON is read differently depending on the slot. What decides it is **who owns the keys in that slot**. The keys of `fields` are a *Content Type*'s field ids, and the keys of `Http.body` are the schema of the API you are calling, so in slots like those, `cat` or `in` has to be a **field name**, not an operator.

| Slot | Applicable fields | How it is read |
|---|---|---|
| Data slot | `fields` (`ResourceCreate`, `ResourceUpdate`, `ResourcePatch`), `Http.body`, `Return.value`, `SetVar.value`, `Cache.value`, `Cache.defaultValue` | A key without `$` is **always a field name**. To use an operation, prefix it with `$`. |
| Expression slot | `If.condition`, `Loop.while`, `version` | The whole value is an expression. An operator can be written as either `cat` or `$cat`. |
| Template slot | Everything else (`url`, `method`, `headers[].value`, `locale`, `order`, `over`, `target.sys.id`, the fields of `EmailSend`, and the value fields of `Signature`, `Hash`, and `Regex`) | These are strings, so only `{ /pointer }` goes in. |
| Literal only | `Regex.pattern`, `Cache.key` | Not a value expression. A `{ /pointer }` written in `Regex.pattern` is not substituted; it becomes part of the pattern. |

The rules fit in two lines.

1. **In a data slot, a key without `$` is always a field name.** To use an operation, prefix the operator with `$`.
2. **Once `$` takes you into an expression, everything inside it is an expression.** Nested operators do not need `$` (you may still add it).

> If in doubt, **prefix every operator with `$`.** That is correct in every slot.

```jsonc
// data slot: cat is a Content Type field name (not the concatenation operation)
"fields": { "cat": { "en-US": "hello" } }

// computing in a data slot: $ only at the boundary, everything inside stays as-is
"fields": { "tier": { "en-US": { "$if": [ { ">=": [ "{ /p/score }", 700 ] }, "gold", "silver" ] } } }

// expression slot: write it as-is
"condition": { "and": [ { "<": [ "{ /a/body/risk }", 0.5 ] }, { ">=": [ "{ /b/body/score }", 700 ] } ] }
```

#### When you need a field name that starts with $: $$ {#dollar-escape}

When the key really does have to start with `$`, as with JSON Schema's `$ref` and `$schema`, write **`$` twice**. `"$$ref"` means the data key `$ref`. **Only one** leading `$` is stripped (`$$$ref` gives `$$ref`), and this applies **to keys only** (a `$` inside a value is left alone).

```jsonc
"body": { "$$ref": "#/components/schemas/Item", "topK": { "$min": [ "{ /payload/fields/k }", 50 ] } }
```

#### The two things that are rejected {#dollar-rejections}

The two cases below are not quietly interpreted as something else; they are rejected as errors.

- **A `$` key alongside another key in the same object** is an error. An operation must be that object's only key, and you can move the sibling data one level out.
- **An unknown `$` key** is an error. `$catt` is not a field named `$catt`. The `$` namespace is reserved for operators.

In an expression slot, an operator name sitting alongside a sibling key is an error too (`{ "and": […], "or": […] }`). That slot has no reading in which the object is data, and every object is judged true, so left alone the condition would quietly always be true.

## Reference: { /json-pointer } {#reference}

Put an RFC 6901 JSON Pointer (which must start with `/`) inside the braces. Whitespace around the braces is allowed (`{ /a/b }` is the same as `{/a/b}`).

### Single pointer vs. mixed template: type rules {#single-vs-mixed}

- When **the entire string is a single pointer**, the value keeps its original type (a number stays a number, an object stays an object, an array stays an array).
- When **it is mixed with literal text, the result is string concatenation**.

```jsonc
"{ /payload/fields/count }"                 // a number value stays a number (e.g. 42)
"{ /payload/fields/tags }"                  // an array stays an array
"page-{ /payload/fields/n }-of-10"          // string concatenation → "page-42-of-10"
"Bearer { /payload/fields/token }"          // string concatenation → "Bearer abc123"
```

### Missing values {#missing-and-escaping}

- When the path is absent or the value is empty, **a single pointer becomes `null`** and **a mixed template becomes an empty string**.

## Context roots: where values come from {#context-roots}

The top-level segment of a `{ /pointer }` is one of the seven below.

| Root | Contents |
|---|---|
| `/payload` | The JSON payload (the input) passed on the call. Example: `{ /payload/fields/email }` |
| `/rawPayload` | The same input, held **exactly as the body string the caller sent** (before parsing). Example: `{ /rawPayload }` |
| `/headers` | The request HTTP headers passed on the call. Keys are lowercase, with a single value per name. Example: `{ /headers/authorization }` |
| `/now` | The time at which execution started. `{ /now/seconds }`, `{ /now/millis }`, `{ /now/iso }` |
| `/<name>` | The **result** of an earlier statement that carries that `name`. Example: `{ /order/sys/id }` |
| `/vars/<name>` | A script-scoped mutable variable declared with `SetVar`. Example: `{ /vars/total }` |
| `/error` | Used only inside a `Try` block's `catch`. The caught error, `{ message }`. Example: `{ /error/message }` |

The six names other than `/<name>` (`payload`, `rawPayload`, `headers`, `now`, `vars`, `error`) are reserved and cannot be used as a statement's `name`. Using the same name would overwrite that root, so it is rejected at save time (see [the binding-name rules under Common fields](/api/reference/script/statements.md#common-fields)).

### /rawPayload: the body exactly as it was sent {#raw-payload}

`/payload` is the parsed value; `/rawPayload` is **the raw string of that same body**. The two point at the same thing without being the same thing. Turning a parsed value back into a string normalizes whitespace, number notation, escapes, and duplicate keys, so you do not get back the bytes that were sent.

That is why **a value computed over the bytes as sent can be handled only through `/rawPayload`.** The representative case is verifying the signature on a payment provider's webhook (see [`Signature`](/api/reference/script/statements.md#signature)). For the everyday references where you pull a value out and use it, use `/payload`.

The call body accepts a JSON object only. An empty body is treated as no body, and a body that is not a JSON object (broken JSON, an array, a scalar, a literal `null`) is rejected without being executed (see [Errors](/api/reference/script/endpoints.md#errors)).

### /now: the time execution started {#now}

`/now` holds the time this execution started, in three forms.

| Pointer | Value |
|---|---|
| `{ /now/seconds }` | Epoch seconds (integer) |
| `{ /now/millis }` | Epoch milliseconds (integer) |
| `{ /now/iso }` | A time string in the platform's notation, the same as `sys.createdAt` (UTC) |

- **One execution has one time only.** It is not a statement that reads a clock but a value planted when execution starts, so two statements never see different values. Each branch of a `Parallel` inherits the same time. Because it is not a statement, it does not count toward the statement count either.
- **There is no field for choosing a time zone.** An epoch value is the same number everywhere, and `iso` is UTC notation.
- You use it to verify a webhook's replay window (how far from now the timestamp carried in the signature is, in seconds). The timestamp usually arrives as a string, but the arithmetic operation converts it to a number, so you compare it as-is.

```jsonc
// is the timestamp carried in the signature within 5 minutes (300 seconds)?
{ "<": [ { "-": [ "{ /now/seconds }", "{ /sig/1 }" ] }, 300 ] }
```

### The shape of a statement's result {#statement-result-shapes}

The result shape of a statement that carries a `name` differs by type.

| Statement | Result shape | Reference example |
|---|---|---|
| `Http` | `{ status, body }` | `{ /resp/status }`, `{ /resp/body/choices/0/message/content }` |
| `ResourceCreate`, `ResourceRead` (single), `ResourceFind` (single) | The resource itself | `{ /post/sys/id }`, `{ /post/fields/title/en-US }` |
| `ResourceForEach` | (During iteration) `name` is the **current item** = the resource itself. Referenced only inside `onEach` | `{ /post/sys/id }`, `{ /post/fields/title/en-US }` |
| `ResourceCount` | The matched count (an integer) | `{ /commentCount }` |
| `ParseJson` | The parsed value itself (object, array, scalar) | `{ /quote/items/0/price }` |
| `Signature` | `Boolean` (whether verification passed) | `{ /verified }` |
| `Hash` | A string (the digest in the notation you declared) | `{ /expectedSign }` |
| `Regex` | `Match` is a `Boolean`. `Capture` is an array (`0` = the whole match, the capture groups from `1`) or `null` when there is no match | `{ /isOrderId }`, `{ /sig/1 }` |

- `ResourceFind` binds `null` when there is no match. Branch on existence with `{ "==": [ "{ /found }", null ] }`.
- `ResourceRead` (single) is an **error** when the target does not exist (you can handle it with `Try`). See [Reading resources in the Statement catalog](/api/reference/script/statements.md#resource-reads) for details.
- Reading a *ServiceUser* gives the member resource itself as the result (`{ /member/sys/id }`). Unlike *Content* and *Media*, its fields are not locale maps but the values themselves. The rules are covered in [Reading the member directory](/api/reference/script/statements.md#service-user-reads).

## Operations and conditions: JsonLogic {#jsonlogic}

When you need a calculation or a condition, use an operator object from the [jsonlogic.com](https://jsonlogic.com) specification.

- **Data access is standardized on `{ /ptr }` references, not the vanilla `var` (dot-path).** The engine resolves the operands' pointers first, then applies the operator.
- **An operator must be that object's only key.** In a data slot only a key prefixed with `$` is an operation; in an expression slot it is an operation whether or not it has `$` (see [Data slots and expression slots](#dollar-prefix)).

### Operator table {#operator-table}

> The names in the table are **operator tokens**. When you use one in a data slot, prefix it with `$` (`cat` becomes `$cat`). In an expression slot, either form works.

| Category | Operator | Meaning and example |
|---|---|---|
| Condition | `if` (alias `?:`) | `{ "if": [cond, then, cond2, then2, …, default] }`. The value of the first true condition, or the last default if none. |
| Logic | `and`, `or` | Short-circuit evaluation. `and` returns the first falsy operand (or the last), `or` the first truthy operand (or the last), **as a value**. |
| Logic | `!` (not), `!!` (to-bool) | `{ "!": x }` negates truthiness; `{ "!!": x }` gives the truthiness. `!!` is often used for existence checks. |
| Equality | `==`, `!=` | **Loose** comparison (compares after numeric coercion; `"1"==1` is true). |
| Equality | `===`, `!==` | **Strict** comparison (type included). |
| Comparison | `<`, `<=`, `>`, `>=` | **Chainable**: `{ "<": [1,2,3] }` means `1<2 AND 2<3`. If a value cannot be made numeric (NaN), it is false. |
| Arithmetic | `+` | The sum of all operands. |
| Arithmetic | `-` | With one operand, negation; with two, subtraction. |
| Arithmetic | `*`, `/`, `%` | Multiplication, division, remainder. |
| Aggregation | `min`, `max` | The minimum and maximum of the operands. |
| String | `cat` | Concatenates all operands as strings. |
| Membership | `in` | `{ "in": [needle, haystack] }`. If the haystack is a string, substring; if a collection, element membership. |
| Array | `merge` | Flattens multiple arrays or values into a single array (used for accumulation). |
| Date | `date` | `{ "date": [value, output unit] }`. Normalizes the value into a comparable instant. The output unit is `millis` (the default), `seconds`, `iso`, or `day`. See [Date normalization](#date-operator). |

The array iteration operators (`map`, `filter`, `reduce`, `all`, `some`, `none`) are not supported. *Script* iterates over an array with `Loop` (see [Loop in the Statement catalog](/api/reference/script/statements.md#loop)). Picking out only the items in a list that meet a date condition is also the job of the read statements, not of iteration. Give the condition to the `where` of [`ResourceFind`](/api/reference/script/statements.md#resource-find) or `ResourceForEach`, and the server filters them and returns them (the operators you can use are in the [operator list](/api/reference/common/query-parameters.md#operators)).

### Numeric coercion and examples {#number-coercion}

The numeric coercion rules are as follows. A number is left as-is, `true` becomes 1, `false` becomes 0, a string is parsed (if it cannot be parsed, the calculation fails), and `null` becomes 0.

**A date string is not a number.** `"2026-10-03"` does not parse as a number, so a comparison operator returns `false` every time, without raising an error. To compare dates, normalize them first with [`date`](#date-operator).

The snippets below assume an **expression slot**. When you put one in a data slot (`fields`, `Http.body`, `Return.value`, `SetVar.value`), prefix **the top-level operator with `$`** and leave the inner operands as they are.

```jsonc
{ "-":  [ "{ /wallet/fields/balance/en-US }", "{ /payload/fields/cost }" ] }   // balance - cost
{ "<":  [ "{ /wallet/fields/balance/en-US }", "{ /payload/fields/cost }" ] }   // balance < cost → boolean
{ "and": [ { "<": [ "{ /a/body/risk }", 0.5 ] }, { ">=": [ "{ /b/body/score }", 700 ] } ] }
{ "cat": [ "id-", "{ /payload/sys/id }" ] }                                    // "id-<uuid>"
{ "!!": "{ /found/sys/id }" }                                                  // true if it exists
{ "$merge": [ "{ /vars/ids }", [ "{ /row/sys/id }" ] ] }                       // array accumulation: SetVar.value is a data slot, so $
{ "if": [ "{ /payload/fields/next }", "{ /payload/fields/next }", "END" ] }     // next if present, otherwise "END"
```

### Date normalization (date) {#date-operator}

A comparison operator turns its operands into numbers and then compares them. A date string is not a number, so that comparison is always `false`, without raising an error. Switching to `==` does not solve it either. When neither side is a number the text itself is compared, so `"2026-10-03"` and `"2026-10-03T00:00:00.000Z"`, two spellings of the same instant, come out as different values. Normalize a date with `date` before comparing it.

```jsonc
{ "date": [ value, output unit ] }   // the output unit can be omitted
{ "date": "2026-10-03" }             // when you pass a single value, you may drop the array
```

There are no dedicated `before`, `after`, or `equal` operators. A normalized value is a number, so you use the comparison, arithmetic, and aggregation operators that already exist.

| What you want to decide | The expression to use |
|---|---|
| a is before b | `{ "<": [ { "date": a }, { "date": b } ] }` |
| a is after b | `{ ">": [ { "date": a }, { "date": b } ] }` |
| The same instant | `{ "==": [ { "date": a }, { "date": b } ] }` |
| The same day (the time ignored) | `{ "==": [ { "date": [a, "day"] }, { "date": [b, "day"] } ] }` |
| Between from and to | `{ "<=": [ { "date": from }, { "date": x }, { "date": to } ] }` (a chained comparison) |
| One week later | `{ "date": [ { "+": [ { "date": x }, 604800000 ] }, "iso" ] }` |
| The number of days between two dates | `{ "/": [ { "-": [ { "date": a }, { "date": b } ] }, 86400000 ] }` |
| The earliest of several dates | `{ "min": [ { "date": a }, { "date": b } ] }` |

An arithmetic result is a millisecond number again, so you can put it through `date` once more to output it as `iso` or `day` ("One week later" in the table above).

```jsonc
// expression slot: is the coupon inside its valid period? the three values may be written in different notations
{ "<=": [
  { "date": "{ /coupon/fields/startsAt/en-US }" },
  { "date": "{ /now/iso }" },
  { "date": "{ /coupon/fields/endsAt/en-US }" }
] }

// expression slot: is the HTTP Date header within 5 minutes (300 seconds) of now?
{ "<": [ { "-": [ "{ /now/seconds }", { "date": [ "{ /headers/date }", "seconds" ] } ] }, 300 ] }
```

#### The inputs it reads {#date-inputs}

All of the values below are read as the same instant.

| Format | Example |
|---|---|
| ISO-8601, RFC 3339 | `2026-10-03T00:00:00Z`, `2026-10-03T00:00:00.000Z`, `2026-10-03T09:00:00+09:00` |
| A time with the seconds or the fraction omitted | `2026-10-03T00:00` |
| A time with a space where the `T` goes | `2026-10-03 00:00:00` |
| A date only (read as midnight UTC) | `2026-10-03` |
| RFC 1123 (the notation of the HTTP `Date` header) | `Sat, 03 Oct 2026 00:00:00 GMT` |
| An epoch number or a numeric string | `1790985600`, `1790985600000`, `"1790985600"` |

- **With no offset, the value is read as UTC.** The offset accepts `+09:00`, `+0900`, `+09`, and `Z`.
- **Parsing is strict.** A date that does not actually exist (`2026-13-45`) fails even when the digit count is right.
- **The unit of an epoch is told apart by the magnitude of its absolute value.** Below 100,000,000,000 it is seconds, and at or above that it is milliseconds. That is why whichever of `{ /now/seconds }` and `{ /now/millis }` you put in, each one is read correctly.
- **The range accepted as an epoch is an absolute value of 100,000,000 or more and less than 100,000,000,000,000.** Because the unit has to be told apart by magnitude, the range is bounded at both ends. A number outside it fails instead of being read as the year 1970. The separator-less date `20261003`, the year `2026`, and the `0` that arrives to mean "no value" fall into this.

#### The output unit {#date-outputs}

The second operand decides the output form. Unit names are case-insensitive.

| Value | Result | Where you use it |
|---|---|---|
| Omitted, `millis` | Epoch milliseconds (a number) | Comparison and arithmetic |
| `seconds` | Epoch seconds (a number). Anything below a second is dropped | External APIs that take epoch seconds |
| `iso` | `2026-10-03T00:00:00.000Z` | Writing to a *Content* `Date` field |
| `day` | `2026-10-03` (in UTC) | Same-day comparison, display |

A name that is not in the list fails, and the error message lists the names you can use.

#### The iso output and writing to a Date field {#date-iso-write}

A *Content* `Date` field accepts a single format on write, `yyyy-MM-ddTHH:mm:ss[.fraction]Z`. The `T`, the seconds, and the trailing `Z` all have to be there, the fraction is optional, and the value is read as UTC. So a `2026-10-03` or a `2026-10-03T09:00:00+09:00` that arrived in the payload is rejected as an invalid value if you put it in as-is. The `iso` output of `date` is exactly this format, so put a date you received through `date` once before you write it to the field.

```jsonc
// data slot: write the payload's "2026-10-03" to the coupon's end date
"fields": { "endsAt": { "en-US": { "$date": [ "{ /payload/fields/endsAt }", "iso" ] } } }
```

#### Values it cannot read {#date-failures}

In the three cases below, that statement fails (status 400). It is a failure that happens during execution, so you can handle it locally with the `catch` of [`Try`](/api/reference/script/statements.md#try).

- The first operand is missing, or a reference did not find a value.
- The value cannot be read as a date. An empty string, a whitespace-only string, a string that is not a date, a date that does not exist, a boolean, an object, and a number outside the accepted range fall into this.
- The output unit name is not in the list.

Not returning `null` when the value is missing is a deliberate contract. `null` becomes `0` under numeric coercion and is therefore compared against the year 1970, so a check with a missing date does not fail but comes out inverted. A coupon that is past its valid period getting through is worse than execution coming to a stop.

### Truthiness {#truthiness}

`if`, `and`, `or`, `!`, `!!`, along with `If.condition` and `Loop.while`, decide true and false by the following rules.

- **falsy**: `null`, `false`, the number `0`, the empty string `""`, and an empty collection (an empty array).
- **truthy**: everything else (nonzero numbers, non-empty strings and arrays, and **every object**).

## Keys can be references too {#keys-as-references}

The **keys** of a map such as `fields` also support `{ /ptr }` references. The key is resolved at runtime.

```jsonc
"fields": { "{ /payload/fields/fieldName }": { "en-US": "{ /payload/fields/fieldValue }" } }
```

If two keys resolve to the same value, they collide and it is an engine error.

## Locale map: rules specific to Content and Media {#locale-value-map}

In WEEGLOO, each field of a *Content* or *Media* is not a value but a per-locale map (for example, `balance` is `{ "en-US": 1, "ko-KR": 10 }`). So you must handle the locale together when you read and write. For *Media* as well, `title` and `description` (scalars) and `file` (the ingest directive) are locale maps. JSON that is not a *Content* or *Media*, such as `/payload` or an HTTP response, is unaffected by this rule (it keeps the structure the schema defines, and a scalar stays a scalar).

### Reading {#reading}

- To get a scalar, specify **down to the locale**: `{ /<name>/fields/<field>/<locale> }` (for example, `{ /post/fields/title/en-US }`).
- Without a locale, `{ /<name>/fields/<field> }` returns **the whole** locale-map object.
- A `localized:false` field lives **only in the default-locale bucket**, so read it with that default-locale code.

### Writing (the fields of ResourceCreate, ResourceUpdate, and ResourcePatch) {#writing}

The value is a **locale map**, `{ "<locale>": <scalar value expression> }`. It is symmetric with reading.

```jsonc
"fields": {
  "title":  { "en-US": "Hello", "ko-KR": "안녕" },   // list buckets for multiple locales
  "status": { "en-US": "paid" }
}
```

- **`ResourceCreate` must include the *Space* default-locale bucket in every field it populates** (the default-locale rule).
- **`ResourceUpdate` is a full replacement.** Fields and locales absent from `fields` are removed (including the file).
- **`ResourcePatch` updates only the specified fields and buckets** (other fields and locales are kept).
- **Delete with a literal `null`**: when the value is a literal `null`, that (field, locale) bucket is deleted (the standard way to clear a specific locale in a Patch). `""` (an empty string) is not a deletion but sets an empty value. When a value expression (`{ /ptr }`) evaluates to null at runtime, it is not a deletion but an **error** (a missing payload is not silently swallowed). Only a literal `null` deletes.
- **`Media` `file`**: the value is not a scalar but an **ingest directive**, `{ "source": …, "encoding": "url"|"base64" }`. What the ingest actually does is covered in [ResourceCreate in the Statement catalog](/api/reference/script/statements.md#resource-create).
- Put a `localized:false` field **only in the default-locale bucket**.
- A locale code (a map key) can also be a `{ /ptr }` reference (see [Keys can be references too](#keys-as-references) above). Use this to build a dynamic locale.

### The locale convenience field {#locale-convenience}

When you give `locale` to `ResourceCreate`, `ResourceUpdate`, or `ResourcePatch`, the engine **automatically wraps each value in `fields` in a `{ <locale>: value }` bucket.** In other words, you only need to give scalars.

```jsonc
// the two below are equivalent
{ "type": "ResourceCreate", "resource": "Content", "contentType": { "sys": { "id": "ct_post" } },
  "locale": "en-US", "fields": { "title": "Hello" } }

{ "type": "ResourceCreate", "resource": "Content", "contentType": { "sys": { "id": "ct_post" } },
  "fields": { "title": { "en-US": "Hello" } } }
```

If you give `locale` while the value already nests a locale map (`{ "en-US": … }`), it becomes **doubly nested** as `{ <locale>: { "en-US": … } }` (an authoring mistake). Standardize on one style: with `locale`, use scalars only; without it, use explicit locale maps only.

### Locales in where and order {#where-order-locale}

- In `where` and `order`, for `fields.X` the engine **automatically applies the *Space* default locale** (the same as a CMA query).
- To specify a particular locale, state it explicitly as `fields.X.<locale>`.

```jsonc
"where": { "fields.slug": { "eq": "{ /payload/fields/slug }" } }   // default-locale slug
"where": { "fields.title.ko-KR": { "prefix": "안" } }              // specific locale
```

## Errors {#errors}

These are the codes that come back when a value expression breaks its rules. The check happens at save time, and the codes for breaking the other static constraints on a definition are in [the errors of Execution semantics, constraints, and security](/api/reference/script/execution-and-limits.md#errors), while the codes that come back when you call a *Script* are in [the errors of Script resource and endpoints](/api/reference/script/endpoints.md#errors). For codes that are common to every resource, see [common errors](/api/reference/common/errors.md).

| Code | Condition |
|---|---|
| `WGL400056` | A `$` operation key was placed in a data slot alongside another key in the same object. |
| `WGL400055` | A `$` key that is not defined as an operator was written in a data slot. |

## Related documents {#related-documents}

- [Statement catalog](/api/reference/script/statements.md): The fields and results of the 25 statement types that use value expressions.
- [Execution semantics, constraints, and security](/api/reference/script/execution-and-limits.md): Execution order, errors, optimistic locking, and static constraints.
- [Cookbook](/api/reference/script/cookbook.md): Complete examples that combine value expressions.
- [Script overview](/api/reference/script.md): The top-level structure and the time given to a single execution.
