astrid-runtime/astrid · error

must contain only ASCII letters, digits, '_' or

Error message

{name} must contain only ASCII letters, digits, '_' or '-'

What it means

Validation guard in validate_topic_segment: the segment contained characters outside ASCII letters, digits, '_' and '-'; this boundary check stops callers from smuggling extra topic segments into the fixed hook route.

Solutions

  1. Replace disallowed characters (dots, slashes, spaces, non-ASCII) in the segment with letters, digits, '_' or '-'
  2. Sanitize host/session/event values before emitting the hook
  3. Use a slug or identifier derived from the value instead of raw user input
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at crates/astrid-emit/src/lib.rs:105 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/3cdad35747dc1791. Report an issue: GitHub.

Appendix: source

Thrown at crates/astrid-emit/src/lib.rs:105

/// Default wait for a policy hook that needs the broker to accept its frame.
/// Observation hooks pass `0` to make the transport fire-and-forget.
pub const DEFAULT_POLICY_TIMEOUT_MS: u64 = 1_000;

/// Validate a host/session/event segment before putting it in a bus topic.
///
/// These values originate in a host hook payload or command line. Keeping
/// the check at this boundary prevents a caller from smuggling additional
/// topic segments into the fixed hook route.
fn validate_topic_segment(name: &str, value: &str) -> Result<()> {
    if value.is_empty() || value.len() > 64 {
        anyhow::bail!("{name} must be 1-64 ASCII characters");
    }
    if !value
        .bytes()
        .all(|byte| byte.is_ascii_alphanumeric() || matches!(byte, b'_' | b'-'))
    {
        anyhow::bail!("{name} must contain only ASCII letters, digits, '_' or '-'");
    }
    Ok(())
}

/// Derive the host hook topic used by the thin `astrid hook` command.
///
/// Every host route carries the session as a topic segment. Codex and the
/// other host runners subscribe to their own `{host}.v1.hook.*.*` namespace;
/// the envelope itself remains the six-field [`build_envelope`] contract.
///
/// # Errors
/// Returns an error when any segment is empty, too long, or contains a topic
/// separator/control character.
pub fn hook_topic(host: &str, session: &str, event: &str) -> Result<String> {
    validate_topic_segment("host", host)?;
    validate_topic_segment("session", session)?;
    validate_topic_segment("event", event)?;

View on GitHub (pinned to affd8760f4)