nautechsystems/nautilus_trader · error · anyhow::Error

{key} `value` contained invalid characters, was {value}

Error message

{key} `value` contained invalid characters, was {value}

What it means

MStr::checked validates that the underlying Ustr for a typed message-topic string contains only valid UTF-8 and none of the wildcard characters `*` or `?`. Topics are pattern-matched internally, so wildcard characters in a stored MStr would corrupt matching; the code bails with this message naming the key type.

Source

Thrown at crates/common/src/msgbus/mstr.rs:55

///
/// - `MStr<Pattern>` - for subscriptions, allows wildcards (`*`, `?`)
/// - `MStr<Topic>` - for publishing, no wildcards
/// - `MStr<Endpoint>` - for direct messages, no wildcards
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(transparent)]
pub struct MStr<T> {
    value: Ustr,
    #[serde(skip)]
    _marker: std::marker::PhantomData<T>,
}

impl<T> MStr<T> {
    #[inline(always)]
    fn checked(value: Ustr, key: &str) -> anyhow::Result<Self> {
        check_valid_string_utf8(value, stringify!(value))?;

        if value.as_bytes().iter().any(|&b| b == b'*' || b == b'?') {
            anyhow::bail!("{key} `value` contained invalid characters, was {value}");
        }

        Ok(Self {
            value,
            _marker: std::marker::PhantomData,
        })
    }
}

impl<T> Display for MStr<T> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.value)
    }
}

impl<T> Deref for MStr<T> {
    type Target = Ustr;

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Remove `*` and `?` from the string before constructing the MStr.
  2. Use the wildcard-aware subscribe/pattern API instead of embedding wildcards in a topic value.
  3. Validate/sanitize user-provided topic config values before creating MStr instances.

Example fix

// before
let topic = MStr::<Topic>::new("data.quotes.*")?;
// after
let topic = MStr::<Topic>::new("data.quotes")?;
// subscribe with pattern instead
msgbus.subscribe_pattern("data.quotes.*", handler);
Defensive patterns

Strategy: validation

Validate before calling

def make_mstr(value: str) -> str:
    if any(ch in value for ch in "*?"):
        raise ValueError(f"topic value must not contain wildcards: {value!r}")
    return value

Try / catch

match MStr::<Topic>::new(user_value) {
    Ok(t) => use(t),
    Err(e) => log::warn!("invalid topic string: {e}"),
}

Prevention

When it happens

Trigger: Constructing any MStr<T> typed constructor (e.g. MStr::topic or MStr::endpoint) with a string containing `*` or `?`, or with non-UTF-8 bytes (via check_valid_string_utf8, which raises its own error).

Common situations: Building topics from user-supplied subscription patterns like 'data.quotes.*' instead of subscribing via a wildcard pattern API; config files where glob-style topic filters are pasted into topic fields; copied topic strings including pattern suffixes.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/a2c8936aebb75a72. Report an issue: GitHub.