Hmbown/CodeWhale · error

percent-encoded Runtime cookie is a valid header

Error message

percent-encoded Runtime cookie is a valid header

What it means

Panic from `HeaderValue::from_str(&cookie)` while setting a Set-Cookie header in the runtime API bootstrap exchange. `from_str` fails only if the value contains non-visible-ASCII bytes; the code asserts the percent-encoded Runtime cookie is always header-safe.

Solutions

  1. Percent-encode the cookie value with `percent_encoding` covering all non-ASCII/control bytes before building the HeaderValue
  2. Validate the cookie with `HeaderValue::from_str(...).is_ok()` and fail loudly at generation time
  3. Log and reject tokens containing invalid characters at issuance instead of at header insertion

Example fix

// before
response.headers_mut().insert(
    header::SET_COOKIE,
    HeaderValue::from_str(&cookie).expect("percent-encoded Runtime cookie is a valid header"),
);
// after
let value = HeaderValue::from_str(&cookie)
    .expect("percent-encoded Runtime cookie is a valid header; ensure token is fully percent-encoded");
response.headers_mut().insert(header::SET_COOKIE, value);
Defensive patterns

Strategy: validation

Validate before calling

debug_assert!(HeaderValue::from_str(&cookie).is_ok(), "cookie contains non-header-safe bytes: {:?}", cookie);

Type guard

fn is_header_safe(v: &str) -> bool { HeaderValue::from_str(v).is_ok() }

Try / catch

let value = HeaderValue::from_str(&cookie).map_err(|e| anyhow::anyhow!("cookie not header-safe: {e}"))?;

Prevention

When it happens

Trigger: `exchange_bootstrap` producing a cookie containing raw non-ASCII, control characters, or newline bytes — i.e., the percent-encoding step failed to encode some character in the Runtime token.

Common situations: A token or session value containing characters outside the encoded alphabet after a change to cookie generation; non-UTF8-safe identifiers being embedded unencoded.

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


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/61488eed6d339401. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/runtime_api/web.rs:134

    };
    let session_token = match web.consume(&nonce, peer.ip()) {
        Ok(token) => token,
        Err(BootstrapError::NonLoopback) => {
            return secured_text(StatusCode::FORBIDDEN, "bootstrap unavailable");
        }
        Err(BootstrapError::Invalid | BootstrapError::Expired) => {
            return secured_text(StatusCode::UNAUTHORIZED, "bootstrap unavailable");
        }
    };

    let cookie = web_session_cookie(&session_token);
    let mut response = (StatusCode::SEE_OTHER, "").into_response();
    response
        .headers_mut()
        .insert(header::LOCATION, HeaderValue::from_static("/"));
    response.headers_mut().insert(
        header::SET_COOKIE,
        HeaderValue::from_str(&cookie).expect("percent-encoded Runtime cookie is a valid header"),
    );
    secure_headers(&mut response, "text/plain; charset=utf-8");
    response
}

pub(super) async fn web_page(State(state): State<RuntimeApiState>) -> Response {
    if state.web.is_none() {
        return not_found();
    }
    secured_asset("text/html; charset=utf-8", WEB_HTML)
}

pub(super) async fn web_styles(State(state): State<RuntimeApiState>) -> Response {
    if state.web.is_none() {
        return not_found();
    }
    secured_asset("text/css; charset=utf-8", WEB_CSS)
}

View on GitHub (pinned to 73e0f67d83)