Hmbown/CodeWhale · error
generated mobile cookie is a valid header
Error message
generated mobile cookie is a valid header
What it means
Same family as the Location expect: the handler sets a Set-Cookie header from `mobile::mobile_session_cookie(...)` and asserts via expect that the cookie string is a valid header value. `HeaderValue::from_str` fails only on control characters, so a panic means the generated cookie (session cookie content) contains illegal bytes such as newline or carriage return.
Solutions
- Sanitize/validate the session cookie value inside mobile_session_cookie before formatting
- Reject control characters when loading the session cookie from the store
- Swap expect for a controlled 500 response so a bad cookie cannot panic the worker
- Test mobile_session_cookie against values containing \r, \n, and non-ASCII bytes
Example fix
// before
HeaderValue::from_str(&cookie).expect("generated mobile cookie is a valid header")
// after
HeaderValue::from_str(&cookie).unwrap_or_else(|_| {
tracing::error!("invalid mobile cookie header");
HeaderValue::from_static("codewhale_mobile=")
}) Defensive patterns
Strategy: validation
Validate before calling
// rust
fn cookie_is_safe(c: &str) -> bool {
!c.is_empty() && c.bytes().all(|b| (33..=126).contains(&b))
}
// check before insert:
assert!(cookie_is_safe(&cookie)); Type guard
// rust
fn safe_cookie(s: &str) -> Option<HeaderValue> {
HeaderValue::from_str(s).ok()
} Try / catch
// rust
if let Ok(v) = HeaderValue::from_str(&cookie) {
response.headers_mut().insert(header::SET_COOKIE, v);
} else {
tracing::error!("invalid mobile cookie");
return StatusCode::INTERNAL_SERVER_ERROR.into_response();
} Prevention
- Validate session cookie values are visible ASCII when loading from the store
- Never concatenate raw user input into cookie strings
- Test cookie builders against \r/\n injection
When it happens
Trigger: `mobile_session_cookie` returns a cookie containing control characters — usually because the underlying session cookie value was corrupted, truncated mid-token, or constructed by concatenating unvalidated input.
Common situations: Upstream session store returning tainted values, manual cookie string manipulation, CRLF injection attempts reaching cookie construction, encoding bugs after a cookie format change.
Related errors
- generated mobile fragment is a valid header
- failed to build HTTP client
- percent-encoded Runtime cookie is a valid header
- ApplyPatchPreflight should serialize
- bing result regex pattern is valid
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/9b3e5c2c4ccba7e4.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/src/runtime_api.rs:1406
}
Err(mobile::BootstrapError::Invalid | mobile::BootstrapError::Expired) => {
return secured_mobile_text(StatusCode::UNAUTHORIZED, "bootstrap unavailable");
}
};
let location = format!(
"/mobile#request_proof={}&stream_ticket={}",
session.request_proof, session.stream_ticket
);
let cookie = mobile::mobile_session_cookie(&session.session_cookie);
let mut response = (StatusCode::SEE_OTHER, "").into_response();
response.headers_mut().insert(
header::LOCATION,
HeaderValue::from_str(&location).expect("generated mobile fragment is a valid header"),
);
response.headers_mut().insert(
header::SET_COOKIE,
HeaderValue::from_str(&cookie).expect("generated mobile cookie is a valid header"),
);
secure_mobile_response(&mut response);
response
}
async fn exchange_mobile_session(State(state): State<RuntimeApiState>, req: Request) -> Response {
let Some(mobile_state) = state.mobile.as_ref() else {
return mobile_not_found();
};
let Some(expected) = state.runtime_token.as_deref() else {
return mobile_not_found();
};
if !auth::request_has_header_runtime_token(&req, expected) {
return mobile_unauthorized();
}
mobile_session_response(mobile_state.issue_session())
}
View on GitHub (pinned to 433685b202)