tinyhumansai/openhuman · error
threadId is required
Error message
threadId is required
What it means
Thrown by update_channel_thread when thread_id is empty after trimming (the channel and action checks are siblings in the same function). The thread id is URL-encoded into PATCH channels/{channel}/threads/{thread_id} — an empty segment would address the collection, not a thread. Input validation only, no request is sent.
Source
Thrown at src/api/rest.rs:1080
bearer_jwt,
Method::POST,
&format!("channels/{encoded}/threads"),
Some(body),
)
.await
}
/// Updates an existing thread (e.g., closing or reopening it).
pub async fn update_channel_thread(
&self,
channel: &str,
bearer_jwt: &str,
thread_id: &str,
action: &str,
) -> Result<Value> {
let channel = channel.trim().trim_matches('/');
anyhow::ensure!(!channel.is_empty(), "channel is required");
anyhow::ensure!(!thread_id.trim().is_empty(), "threadId is required");
anyhow::ensure!(
action == "close" || action == "reopen",
"action must be 'close' or 'reopen'"
);
let encoded_channel = urlencoding::encode(channel);
let encoded_thread = urlencoding::encode(thread_id.trim());
let body = serde_json::json!({ "action": action });
self.authed_json(
bearer_jwt,
Method::PATCH,
&format!("channels/{encoded_channel}/threads/{encoded_thread}"),
Some(body),
)
.await
}
/// Lists threads in a communication channel, optionally filtering by status.
pub async fn list_channel_threads(View on GitHub (pinned to a221052e0d)
Solutions
- Only enable close/reopen once the backend thread id is persisted
- Validate thread_id non-empty at the action boundary
- Guard at the call site with trim()
Example fix
// before client.update_channel_thread(&channel, &jwt, &thread_id, "reopen").await?; // after let thread_id = thread_id.trim(); anyhow::ensure!(!thread_id.is_empty(), "threadId is required (backend thread not created yet?)"); client.update_channel_thread(&channel, &jwt, thread_id, "reopen").await?;
Defensive patterns
Strategy: validation
Validate before calling
let thread_id = thread_id.trim(); anyhow::ensure!(!thread_id.is_empty(), "threadId is required (backend thread not created yet?)"); client.update_channel_thread(&channel, &jwt, thread_id, action).await?;
Type guard
fn has_thread_id(s: &str) -> bool {
!s.trim().is_empty()
} Prevention
- Only enable close/reopen once the backend thread id is persisted locally
- Give pending local threads a typed Pending state instead of an empty-string id
When it happens
Trigger: Calling update_channel_thread with thread_id = "" or " " — e.g. the close/reopen action fired on a locally-created thread before the backend thread id was stored.
Common situations: UI optimistically creates a thread row with an empty pending id, or the thread_id field was renamed and now reads a missing key.
Related errors
- threads_token_usage returned an empty envelope
- API base URL must be an absolute http(s) URL with host
- provider is required
- login token is required
- channel is required
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/e9541d31b0810516.
Report an issue: GitHub.