{"record":{"id":"b5c93cbe58cfed8a","repo":"unicity-aos/aos-ce","slug":"aos-mcp-could-not-audit-rejected-hook-message-error","errorCode":null,"errorMessage":"aos-mcp: could not audit rejected hook message: {error}","messagePattern":"aos-mcp: could not audit rejected hook message: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"capsules/capsule-mcp/src/host_hooks.rs","lineNumber":377,"sourceCode":"}\n\nfn is_lower_hex(value: &str, expected_len: usize) -> bool {\n    value.len() == expected_len\n        && value\n            .bytes()\n            .all(|byte| byte.is_ascii_digit() || (b'a'..=b'f').contains(&byte))\n}\n\nfn reject(host: &str, event: &str, reason: &str) {\n    if let Err(error) = ipc::publish_json(\n        \"astrid.v1.audit.hook_ingress_rejected\",\n        &serde_json::json!({\n            \"host\": bounded_audit(host),\n            \"event\": bounded_audit(event),\n            \"reason\": reason,\n        }),\n    ) {\n        log::warn(format!(\n            \"aos-mcp: could not audit rejected hook message: {error}\"\n        ));\n    }\n}\n\nfn bounded_audit(value: &str) -> &str {\n    let end = value.floor_char_boundary(value.len().min(128));\n    &value[..end]\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    fn request() -> HostHookRequest {\n        let token = \"a\".repeat(64);\n        let route_id = derive_route_id(\"codex\", \"codex-session\", &token);\n        let correlation_id = \"b\".repeat(32);","sourceCodeStart":359,"sourceCodeEnd":395,"githubUrl":"https://github.com/unicity-aos/aos-ce/blob/f6f22024fb1e8d122f28a1b4a9f75aee448ae839/capsules/capsule-mcp/src/host_hooks.rs#L359-L395","documentation":"When capsule-mcp rejects a host hook message, it attempts to write an audit record (host, event, reason) via a logging/audit sink. If that audit write fails, it logs this warning; the message is still rejected. The warning exists so rejections remain auditable — losing the audit trail is the real concern, not the rejection itself.","triggerScenarios":"The audit sink call in reject() (invoked from handle and relay_response paths) returns Err after building the json!({host, event, reason}) payload — e.g., audit KV/log store unavailable or write rejected.","commonSituations":"Audit storage outage or quota exhaustion while hook messages are being rejected; misconfigured audit sink; host/event strings rejected by the sink.","solutions":["Inspect the {error} in the log to identify the failing audit sink and fix its availability/configuration.","Verify the audit sink credentials/permissions allow writes.","Fall back to a secondary audit channel (stdout log capture) until the sink recovers.","Re-audit manually if compliance requires a record of the rejection."],"exampleFix":"// before\nif let Err(error) = audit::record(&serde_json::json!({\n    \"host\": bounded_audit(host), \"event\": bounded_audit(event), \"reason\": reason,\n})) {\n    log::warn(format!(\"aos-mcp: could not audit rejected hook message: {error}\"));\n}\n// after\nif let Err(error) = audit::record(&serde_json::json!({\n    \"host\": bounded_audit(host), \"event\": bounded_audit(event), \"reason\": reason,\n})) {\n    log::warn(format!(\"aos-mcp: could not audit rejected hook message: {error}\"));\n    log::info(\"AUDIT-FALLBACK host={host} event={event} reason={reason}\");\n}","handlingStrategy":"fallback","validationCode":"// verify audit sink writability before processing hooks\nlet audit_ok = audit::health_check().is_ok();","typeGuard":null,"tryCatchPattern":"if let Err(e) = audit::record(&payload) {\n    log::warn(\"audit write failed: {e}\");\n    // emit to secondary log channel\n}","preventionTips":["Health-check the audit sink at startup","Keep a secondary audit channel (structured stdout)","Monitor audit write failure rates"],"tags":["audit","kv","logging","hook"],"backgroundTag":"database-write-failed","analyzedSha":"f6f22024fb1e8d122f28a1b4a9f75aee448ae839","analyzedAt":"2026-09-13T03:04:44.565Z","contentChangedAt":"2026-09-13T03:04:44.565Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}