Hmbown/CodeWhale · error
operation_key cannot contain control characters
Error message
operation_key cannot contain control characters
What it means
validate_runtime_turn_operation_key character check (after the empty, length, and trim guards): the key contains control characters, which would corrupt idempotency-key matching in the durable binding store, so such keys are rejected.
Solutions
- Sanitize the key: filter out or replace control chars before calling
- Join multi-part data with a printable separator like ':' instead of newline
- Escape/encode raw-derived content (hex or base64) before embedding it in the key
Example fix
// before let key = raw_output; // may contain \n // after let key: String = raw_output.chars().filter(|c| !c.is_control()).collect();
Defensive patterns
Strategy: validation
Validate before calling
let sanitized: String = key.chars().filter(|c| !c.is_control()).collect(); assert_eq!(sanitized, key, "operation_key must not contain control chars");
Prevention
- Use printable separators (':') when joining key parts
- Hex/base64-encode raw-derived content
- Never pass process output or file bytes unescaped as a key
When it happens
Trigger: Passing an operation_key containing chars like \n, \t, \r, \0, or other Unicode control codepoints, typically from binary data, raw process output, or multi-line heredocs.
Common situations: Building keys from command output or file contents that include newlines; programmatic key generation that accidentally joins with '\n'.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- invalid-base64
- invalid base64
- operation_key cannot contain leading or trailing whitespace
- operation_key cannot exceed
- Runtime is missing its request identity.
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/af16b2f81a645afd.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/runtime_threads.rs:3508
InvalidRequest,
#[error("Turn operation acceptance is incomplete; retry lookup")]
Incomplete,
#[error("Turn operation lookup unavailable")]
Unavailable,
}
fn validate_runtime_turn_operation_key(value: &str) -> Result<()> {
if value.is_empty() {
bail!("operation_key cannot be empty");
}
if value.len() > MAX_RUNTIME_TURN_OPERATION_KEY_BYTES {
bail!("operation_key cannot exceed {MAX_RUNTIME_TURN_OPERATION_KEY_BYTES} UTF-8 bytes");
}
if value.trim() != value {
bail!("operation_key cannot contain leading or trailing whitespace");
}
if value.chars().any(char::is_control) {
bail!("operation_key cannot contain control characters");
}
Ok(())
}
fn validate_sha256_fingerprint(value: &str, label: &str) -> Result<()> {
if value.len() != 64 || !value.bytes().all(|byte| byte.is_ascii_hexdigit()) {
bail!("{label} must be a SHA-256 hex digest");
}
Ok(())
}
fn runtime_turn_operation_key_fingerprint(
owner_id: &str,
thread_id: &str,
operation_key: &str,
) -> Result<String> {
validate_runtime_turn_operation_key(operation_key)?;
Ok(crate::hashing::sha256_hex(format!(View on GitHub (pinned to 73e0f67d83)