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
- Replace disallowed characters (dots, slashes, spaces, non-ASCII) in the segment with letters, digits, '_' or '-'
- Sanitize host/session/event values before emitting the hook
- 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)