Listeners

Errors from the listeners: block — cross-stream event subscriptions.

12 error codes in this section.

VERR_LISTENER_EVENT_NOT_FOUND

Listener references unknown event. A listener’s on: references an event type that is not registered in the event registry.

Impact: Listener is dead — it will never fire.

✗ Won't compile
listeners:
  update_user:
    on: OrderShipped   # not in events
✓ Fixed
# Register OrderShipped in app.causet, or use the correct event name.

VERR_LISTENER_EMPTY_MUTATE

Listener mutate block is empty. A listener’s mutate: block is present but contains no operations.

Impact: Listener fires but makes no changes — silent no-op.

✗ Won't compile
listeners:
  update_user:
    on: OrderPlaced
    mutate: []   # empty
✓ Fixed
listeners:
  update_user:
    on: OrderPlaced
    mutate:
      - entity: user
        ops:
          - op: add
            path: /order_count
            value: 1

VERR_LISTENER_INVALID_OP

Invalid op in listener mutation. A listener mutation uses an op that is not allowed in listeners. Listeners may only mutate entity state, not emit events.

Impact: Listener cannot fire; entity state is not updated.

✗ Won't compile
mutate:
  - entity: user
    ops:
      - op: emit   # not allowed in listeners
        event_type: UserUpdated
✓ Fixed
mutate:
  - entity: user
    ops:
      - op: add
        path: /order_count
        value: 1

VERR_LISTENER_FIELD_NOT_FOUND

Listener mutation targets nonexistent field. A listener mutation references a field that does not exist on the target entity schema.

Impact: Mutation fails; entity state is not updated.

✗ Won't compile
ops:
  - op: set
    path: /last_seen_at   # field not in entity schema
✓ Fixed
# Add 'last_seen_at' to the target entity's field definitions first.

VERR_LISTENER_OP_TYPE_MISMATCH

Listener op incompatible with field type. A listener mutation op is incompatible with the target field’s declared type.

Impact: Mutation throws at runtime; entity state is not updated.

✗ Won't compile
# username is type: string
ops:
  - op: add
    path: /username
    value: 1   # add on string field
✓ Fixed
# Use op: set for string fields, op: add/sub only for numeric fields.

VERR_LISTENER_INVALID_TARGET

Listener target references undefined resolve alias. A listener mutation targets an entity via an alias not declared in the listener’s resolve: block.

Impact: Mutation cannot resolve its target entity; it is silently skipped.

✗ Won't compile
mutate:
  - entity: follower   # 'follower' not in resolve:
    ops: []
✓ Fixed
# Add 'follower' to the listener's resolve: block.

VERR_LISTENER_DUPLICATE_ALIAS

Duplicate listener resolve alias. The same alias is defined twice in a listener’s resolve: block.

Impact: Second definition overrides first; listener resolves the wrong entity.

✗ Won't compile
resolve:
  user: { ... }
  user: { ... }   # duplicate
✓ Fixed
# Use unique alias names in the resolve: block.

VERR_LISTENER_INVALID_LOOKUP

Invalid lookup in listener resolve. A listener resolve: lookup expression is malformed — wrong syntax or missing required parts.

Impact: Listener cannot resolve its target; all mutations are skipped.

✗ Won't compile
resolve:
  user: lookup(users)   # missing ID argument
✓ Fixed
resolve:
  user: lookup(users, event.payload.user_id)

VERR_LISTENER_RESOLVE_STREAM_NOT_FOUND

Listener resolve references unknown stream. A listener resolve: block references a stream name that does not match any defined state.

Impact: Listener cannot resolve its target entity.

✗ Won't compile
resolve:
  user: lookup(unknown_stream, event.payload.user_id)
✓ Fixed
# Ensure the stream name matches a defined state name.

VERR_LISTENER_CIRCULAR_CHAIN

Circular listener event chain. A listener chain forms a cycle: event A triggers listener emitting event B, which triggers a listener emitting event A.

Impact: Infinite loop at runtime; Kafka consumer stalls.

✗ Won't compile
# EventA → ListenerA emits EventB → ListenerB emits EventA
✓ Fixed
# Redesign the listener chain to form a DAG (no cycles).

VERR_EMIT_CIRCULAR_CHAIN

Circular action-emit chain. An action emits an event that, through listeners and routing, eventually triggers the same action again.

Impact: Infinite loop at runtime; intent processing stalls.

✗ Won't compile
# Action A → emit Event1 → listener → Action A
✓ Fixed
# Add a termination condition or restructure the event flow to be acyclic.

VERR_LISTENER_NON_DETERMINISTIC

Non-deterministic expression in listener. A listener mutation uses a non-deterministic expression (now(), random(), or external state).

Impact: Replay of the triggering event produces different state mutations.

✗ Won't compile
ops:
  - op: set
    path: /updated_at
    value: "#{ now() }"   # non-deterministic
✓ Fixed
ops:
  - op: set
    path: /updated_at
    value: "#{ event.ts }"