{"record":{"id":"5dc93c3c0e8e139b","repo":"databendlabs/databend","slug":"login-handler-expect-session-id-in-ctx","errorCode":null,"errorMessage":"login_handler expect session id in ctx","messagePattern":"login_handler expect session id in ctx","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/query/service/src/servers/http/v1/session/login_handler.rs","lineNumber":103,"sourceCode":"#[derive(Deserialize)]\nstruct LoginQuery {\n    disable_session_token: Option<bool>,\n}\n\n///  # For client/driver developer:\n/// - It is encouraged to call `/v1/session/login` when establishing connection, not mandatory for now.\n/// - May get 404 when talk to old server, may check `/health` (no `/v1` prefix) to ensure the host:port is not wrong.\n#[poem::handler]\n#[async_backtrace::framed]\npub async fn login_handler(\n    ctx: &HttpQueryContext,\n    Json(req): Json<LoginRequest>,\n    Query(query): Query<LoginQuery>,\n) -> PoemResult<impl IntoResponse> {\n    let session_id = ctx\n        .client_session_id\n        .as_ref()\n        .expect(\"login_handler expect session id in ctx\")\n        .clone();\n    check_login(ctx, &req)\n        .await\n        .map_err(HttpErrorCode::bad_request)?;\n    let version = &ctx.version.semantic;\n    let server_arrow_features = (SERVER_MAX_ARROW_RESULT_VERSION\n        >= ARROW_FEATURE_NEGOTIATION_VERSION)\n        .then_some(ArrowFeatures::decimal64_enabled());\n    let id_only = || {\n        Ok(Json(LoginResponse {\n            version: version.to_string(),\n            session_id: session_id.clone(),\n            server_max_arrow_result_version: SERVER_MAX_ARROW_RESULT_VERSION,\n            server_arrow_features: server_arrow_features.clone(),\n            tokens: None,\n        }))\n    };\n","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/databendlabs/databend/blob/288d84d76e20a2f8f7173bda9691eb6ece301aa9/src/query/service/src/servers/http/v1/session/login_handler.rs#L85-L121","documentation":"The HTTP login handler requires the client to present a session id (`client_session_id`) in the request context. `expect(\"login_handler expect session id in ctx\")` panics when the extractor that populates `ctx.client_session_id` did not run or the request omitted the session-id cookie/header, instead of returning a clean 400.","triggerScenarios":"POST /v1/session/login without the session-id cookie or header that the session middleware/extractor normally injects; calling the handler outside the configured router (e.g. tests or proxied requests stripping headers).","commonSituations":"See trigger scenarios.","solutions":["Send the required session id (cookie or header) with the login request.","Verify middleware/extractors that set client_session_id are attached to the login route.","Replace the expect with a proper poem error: return 400 bad_request when client_session_id is missing.","Check reverse-proxy config isn't dropping cookies/custom headers."],"exampleFix":"// before\nlet session_id = ctx.client_session_id.as_ref().expect(\"login_handler expect session id in ctx\").clone();\n// after\nlet session_id = ctx.client_session_id.clone().ok_or_else(||\n    poem::Error::from_string(\"session id is required\", poem::http::StatusCode::BAD_REQUEST))?;","handlingStrategy":"validation","validationCode":"// client: ensure session id is attached\nif (!headers.has('x-databend-session-id') && !cookies.has('session_id')) {\n  throw new Error('login requires a session id cookie/header');\n}","typeGuard":"fn has_session_id(ctx: &HttpContext) -> bool { ctx.client_session_id.is_some() }","tryCatchPattern":"// server-side fix\nmatch ctx.client_session_id.as_ref() {\n    Some(id) => id.clone(),\n    None => return Err(poem::Error::from_string(\"missing session id\", poem::http::StatusCode::BAD_REQUEST)),\n}","preventionTips":["Always send the session-id cookie/header on /v1/session/login","Verify reverse proxies don't strip cookies or custom headers","Keep session middleware attached to login routes","Prefer returning 4xx over expect in HTTP handlers"],"tags":["http","rust","panic","session","authentication"],"backgroundTag":"authentication-required","analyzedSha":"288d84d76e20a2f8f7173bda9691eb6ece301aa9","analyzedAt":"2026-09-11T11:29:36.208Z","contentChangedAt":"2026-09-11T11:29:36.208Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}