{"record":{"id":"f57ce429a91a6ddb","repo":"tinyhumansai/openhuman","slug":"action-must-be-close-or-reopen","errorCode":null,"errorMessage":"action must be 'close' or 'reopen'","messagePattern":"action must be 'close' or 'reopen'","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/api/rest.rs","lineNumber":1081,"sourceCode":"            Method::POST,\n            &format!(\"channels/{encoded}/threads\"),\n            Some(body),\n        )\n        .await\n    }\n\n    /// Updates an existing thread (e.g., closing or reopening it).\n    pub async fn update_channel_thread(\n        &self,\n        channel: &str,\n        bearer_jwt: &str,\n        thread_id: &str,\n        action: &str,\n    ) -> Result<Value> {\n        let channel = channel.trim().trim_matches('/');\n        anyhow::ensure!(!channel.is_empty(), \"channel is required\");\n        anyhow::ensure!(!thread_id.trim().is_empty(), \"threadId is required\");\n        anyhow::ensure!(\n            action == \"close\" || action == \"reopen\",\n            \"action must be 'close' or 'reopen'\"\n        );\n        let encoded_channel = urlencoding::encode(channel);\n        let encoded_thread = urlencoding::encode(thread_id.trim());\n        let body = serde_json::json!({ \"action\": action });\n        self.authed_json(\n            bearer_jwt,\n            Method::PATCH,\n            &format!(\"channels/{encoded_channel}/threads/{encoded_thread}\"),\n            Some(body),\n        )\n        .await\n    }\n\n    /// Lists threads in a communication channel, optionally filtering by status.\n    pub async fn list_channel_threads(\n        &self,","sourceCodeStart":1063,"sourceCodeEnd":1099,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/src/api/rest.rs#L1063-L1099","documentation":"anyhow::ensure! argument guard in update_channel_thread: the action parameter is neither 'close' nor 'reopen' — the only two actions the backend thread-update route accepts. The guard fails fast client-side so an invalid action never reaches the wire as a 400 from the backend.","triggerScenarios":"Thrown at src/api/rest.rs:1081 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Pass action as exactly \"close\" or \"reopen\"","Check for typos/casing in the caller (e.g. \"Close\", \"archive\")","Use the thread-listing UI flow that already emits the correct verbs"],"exampleFix":null,"handlingStrategy":"validation","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"}