nautechsystems/nautilus_trader · error · anyhow::Error

Unknown execution event marker {event}

Error message

Unknown execution event marker {event}

What it means

`mark_execution_event_emitted` persists that an order event was dispatched so it is not re-emitted after restart; it recognizes exactly three event markers — 'acknowledgement', 'fill', 'terminal' — each mapped to a guarded UPDATE. Any other string hits the catch-all bail. A second ensure in the same method also fails when the intent row is absent or the opposing marker gate rejects the update.

Source

Thrown at crates/adapters/blockchain/src/cache/database.rs:3893

    ///
    /// Returns an error if the event kind is unknown, the intent is absent, the opposing
    /// terminal marker is already set, or persistence fails.
    pub async fn mark_execution_event_emitted(
        &self,
        intent_id: i64,
        event: &str,
    ) -> anyhow::Result<()> {
        let statement = match event {
            "acknowledgement" => {
                "UPDATE execution_intent SET acknowledgement_emitted = TRUE, updated_at = NOW() WHERE id = $1"
            }
            "fill" => {
                "UPDATE execution_intent SET fill_emitted = TRUE, active = CASE WHEN status = 'finalized' THEN FALSE ELSE active END, updated_at = NOW() WHERE id = $1 AND NOT terminal_emitted"
            }
            "terminal" => {
                "UPDATE execution_intent SET terminal_emitted = TRUE, active = CASE WHEN status IN ('finalized', 'reverted') THEN FALSE ELSE active END, updated_at = NOW() WHERE id = $1 AND NOT fill_emitted"
            }
            _ => anyhow::bail!("Unknown execution event marker {event}"),
        };
        let result = sqlx::query(statement)
            .bind(intent_id)
            .execute(&self.pool)
            .await
            .map_err(|e| anyhow::anyhow!("Failed to mark execution {event} emitted: {e}"))?;
        anyhow::ensure!(
            result.rows_affected() == 1,
            "Execution intent {intent_id} cannot mark {event} emitted"
        );
        Ok(())
    }

    /// Updates the status of a persisted execution transaction record.
    ///
    /// # Errors
    ///
    /// Returns an error if the database operation fails.

View on GitHub (pinned to 2114cf6f76)

Solutions

  1. Use exactly one of the lowercase literals: 'acknowledgement', 'fill', 'terminal'.
  2. Better: model the kind as an enum and convert to the string at the boundary so invalid values fail to compile.
  3. If the value arrives from config or a queue, validate it against the allowed set before the call.
  4. If the string looks correct, check the follow-on ensure ('cannot mark {event} emitted') — that indicates a missing intent row or an opposing-marker conflict, not an unknown marker.

Example fix

// before
executor.database.mark_execution_event_emitted(intent_id, 'Fill').await?; // bails: unknown marker

// after: type-safe marker
#[derive(Clone, Copy)]
enum ExecutionEventMarker { Acknowledgement, Fill, Terminal }
impl ExecutionEventMarker {
    fn as_str(self) -> &'static str {
        match self { Self::Acknowledgement => 'acknowledgement', Self::Fill => 'fill', Self::Terminal => 'terminal' }
    }
}
executor.database.mark_execution_event_emitted(intent_id, ExecutionEventMarker::Fill.as_str()).await?;
Defensive patterns

Strategy: type-guard

Validate before calling

const MARKERS: &[&str] = &['acknowledgement', 'fill', 'terminal'];
anyhow::ensure!(MARKERS.contains(&event), 'event must be one of {MARKERS:?}, got {event}');

Type guard

#[derive(Clone, Copy)]
enum ExecutionEventMarker { Acknowledgement, Fill, Terminal }
impl ExecutionEventMarker {
    fn as_str(self) -> &'static str {
        match self {
            Self::Acknowledgement => 'acknowledgement',
            Self::Fill => 'fill',
            Self::Terminal => 'terminal',
        }
    }
}
// only ever pass marker.as_str(); invalid kinds cannot be expressed

Try / catch

Match the error: if the message starts with 'Unknown execution event marker', fix the caller's string (exact lowercase literal) — retrying with the same value will always fail. A 'cannot mark ... emitted' message instead means a missing intent row or opposing-marker conflict.

Prevention

When it happens

Trigger: Calling the method with a string other than the three exact literals: 'Fill' (wrong case), 'reject', 'ack', a trailing space, or a newly introduced event kind the running build does not know.

Common situations: Custom tooling calling this internal database API directly; refactors that rename event kinds without updating call sites; version mixing where a caller emits a newer event vocabulary than the database layer understands.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@2114cf6f76 (2026-08-21). Data as JSON: /api/errors/c95f96993393ede2. Report an issue: GitHub.