{"record":{"id":"4f8e645638b90e37","repo":"tinyhumansai/openhuman","slug":"name-e","errorCode":null,"errorMessage":"{name}: {e}","messagePattern":"\\{name\\}: \\{e\\}","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/openhuman/hosted/billing/tools.rs","lineNumber":19,"sourceCode":"//! LLM-callable wrappers over the `billing` domain.\n//!\n//! Reads (plan/balance/transactions/cards/coupons/auto-recharge + the Stripe\n//! portal link) are default-ON. Every money-moving or payment-method mutator\n//! ships default-OFF via `tools/user_filter.rs` (`billing_writes` toggle);\n//! `billing_delete_card` is `Dangerous`.\n\nuse std::sync::Arc;\n\nuse async_trait::async_trait;\nuse serde_json::{json, Value};\n\nuse crate::openhuman::config::Config;\nuse crate::openhuman::hosted::billing;\nuse crate::openhuman::tools::traits::{PermissionLevel, Tool, ToolResult};\n\nmacro_rules! emit {\n    ($outcome:expr, $name:literal) => {{\n        let outcome = $outcome.map_err(|e| anyhow::anyhow!(concat!($name, \": {}\"), e))?;\n        Ok(ToolResult::success(serde_json::to_string(&outcome.value)?))\n    }};\n}\n\nfn req_str(args: &serde_json::Value, key: &str) -> anyhow::Result<String> {\n    args.get(key)\n        .and_then(Value::as_str)\n        .map(str::trim)\n        .filter(|s| !s.is_empty())\n        .map(str::to_string)\n        .ok_or_else(|| anyhow::anyhow!(\"missing required string argument `{key}`\"))\n}\n\n/// Read tool over a `&Config`-only `async fn -> Result<RpcOutcome<Value>, String>`.\nmacro_rules! cfg_read {\n    ($ty:ident, $name:literal, $fn:ident, $desc:literal) => {\n        pub struct $ty {\n            config: Arc<Config>,","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/src/openhuman/hosted/billing/tools.rs#L1-L37","documentation":"Generic emit! macro wrapper for the billing tools: a billing-domain RPC returned an RpcOutcome error and the macro prefixes it with the tool name before propagating. One message shape covers every billing read/mutator; the underlying error text distinguishes the actual backend/domain cause.","triggerScenarios":"Thrown at src/openhuman/hosted/billing/tools.rs:19 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Read the suffixed error text for the billing-domain cause","Verify session/auth state for backend billing calls","Retry transient backend failures once"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}