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

  1. Normalize the provider id to [A-Za-z0-9_] only (replace dashes/dots with underscores) before validating
  2. Confirm the id is genuinely from the provider and non-degenerate (≥5 chars)
  3. Truncate or hash composite ids to stay within 80 bytes
  4. 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

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


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)