{"record":{"id":"248f05a958a1174e","repo":"astrid-runtime/astrid","slug":"a-topic-is-required-positional-topic-or-to","errorCode":null,"errorMessage":"a topic is required (positional `<topic>` or `--topic <topic>`)","messagePattern":"a topic is required \\(positional `<topic>` or `--topic <topic>`\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-emit/src/lib.rs","lineNumber":141,"sourceCode":"\n    Ok(format!(\"{host}.v1.hook.{session}.{event}\"))\n}\n\nimpl Args {\n    /// Resolve the single topic from whichever form was supplied.\n    ///\n    /// `clap`'s `conflicts_with` already rejects supplying both, so the\n    /// only failure this surfaces is supplying neither.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if no topic was supplied (neither positional\n    /// nor `--topic`).\n    pub fn resolve_topic(self) -> Result<String> {\n        match (self.topic_positional, self.topic_flag) {\n            (Some(t), None) | (None, Some(t)) => Ok(t),\n            (None, None) => {\n                anyhow::bail!(\"a topic is required (positional `<topic>` or `--topic <topic>`)\")\n            },\n            // Unreachable in practice: clap's `conflicts_with` rejects\n            // both-supplied before we get here. Kept exhaustive so the\n            // match doesn't rely on that invariant silently.\n            (Some(_), Some(_)) => {\n                anyhow::bail!(\"specify the topic exactly once (positional OR --topic, not both)\")\n            },\n        }\n    }\n}\n\n/// Outcome of an [`emit`] call: what to print to stderr (if anything)\n/// and which process exit code to return. The fixed `{\"continue\":true}`\n/// stdout line is the caller's responsibility and is emitted\n/// unconditionally regardless of this outcome.\n#[derive(Debug)]\n#[must_use]\npub struct Outcome {","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-emit/src/lib.rs#L123-L159","documentation":"Resolution guard in Args::resolve_topic: neither the positional `<topic>` argument nor the `--topic` flag was supplied. clap's conflicts_with already rejects supplying both, so this error exclusively covers the neither-supplied case. Emitting an event requires exactly one topic to build the `{host}.v1.hook.{session}.{event}` topic name.","triggerScenarios":"Thrown at crates/astrid-emit/src/lib.rs:141 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Pass the topic positionally, e.g. astrid-emit sage.v1.hook.before_tool_call","Or pass it as a flag: astrid-emit --topic sage.v1.hook.before_tool_call","Check the wrapper script or host hook config that dropped the topic argument"],"exampleFix":null,"handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}