Hmbown/CodeWhale · error
invalid
Error message
invalid {label} What it means
validate_native_record_id validates native (provider-side) record ids: length 5–80 bytes, composed only of ASCII alphanumerics and underscore. The bail message uses the caller-supplied label (e.g. "invalid native turn id"). It exists because native ids become state keys and filesystem-adjacent identifiers, so only a conservative charset is accepted.
Solutions
- Normalize the provider id to [A-Za-z0-9_] only (replace dashes/dots with underscores) before validating
- Confirm the id is genuinely from the provider and non-degenerate (≥5 chars)
- Truncate or hash composite ids to stay within 80 bytes
- If a legitimate provider id format is being rejected, widen the validator's charset in code with a test
Example fix
// before let id = "turn_9f86d081-884c-7d65"; // dashes not allowed // after let id = "turn_9f86d081_884c_7d65"; // alphanumerics + underscore only
Defensive patterns
Strategy: validation
Validate before calling
fn looks_like_native_record_id(value: &str) -> bool {
(5..=80).contains(&value.len())
&& value.bytes().all(|b| b.is_ascii_alphanumeric() || b == b'_')
}
fn normalize_native_record_id(raw: &str) -> String {
let cleaned: String = raw.chars().map(|c| if c.is_ascii_alphanumeric() { c } else { '_' }).collect();
cleaned.chars().take(80).collect()
} Type guard
fn as_native_record_id(value: &str) -> Option<&str> {
looks_like_native_record_id(value).then_some(value)
} Try / catch
if !looks_like_native_record_id(&native_id) {
let native_id = normalize_native_record_id(&native_id);
validate_native_record_id(&native_id, "native turn id")?;
} Prevention
- Normalize provider ids (dashes/dots to underscores) before storing them as native record ids
- Reject empty/degenerate ids at the provider-response boundary rather than at persist time
- Keep composite ids within 80 bytes; hash when concatenating long parts
When it happens
Trigger: Calling validate_native_record_id(value, label) — for native turn ids or other native records — with a value shorter than 5, longer than 80, or containing dashes, dots, colons, spaces, Unicode, or other non-[A-Za-z0-9_] characters.
Common situations: Passing provider ids that use dashes (common UUID forms) or dots where only alphanumerics/underscore are allowed; empty or near-empty strings from failed provider responses; very long composite ids over 80 bytes.
Understand the failure class
Background: "invalid id" errors: invalid identifier format — why libraries reject IDs before lookup, and how to fix them — this error's family across 37 libraries.
Related errors
- cloud job id must look like cloud_
- DeepSeek Harness credentials line
- Invalid durable task id
- Invalid preallocated task id: expected task_<16hex>
- invalid Runtime Chat
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/004e364897444858.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/runtime_chat_relay.rs:1741
if value.len() != 35
|| !value.starts_with("local_turn_")
|| !value[11..]
.bytes()
.all(|byte| byte.is_ascii_digit() || matches!(byte, b'a'..=b'f'))
{
bail!("invalid Runtime Chat virtual turn id");
}
Ok(())
}
fn validate_native_record_id(value: &str, label: &str) -> Result<()> {
if value.len() < 5
|| value.len() > 80
|| !value
.bytes()
.all(|byte| byte.is_ascii_alphanumeric() || byte == b'_')
{
bail!("invalid {label}");
}
Ok(())
}
fn validate_route_id(value: &str, label: &str) -> Result<()> {
if !crate::runtime_api::runtime_chat_route_id_is_safe(value) {
bail!("invalid Runtime Chat {label}");
}
Ok(())
}
fn validate_model_id(value: &str) -> Result<()> {
if !crate::runtime_api::runtime_chat_model_id_is_safe(value) {
bail!("invalid Runtime Chat model id");
}
Ok(())
}
View on GitHub (pinned to 73e0f67d83)