{"record":{"id":"aaacbf1bf5339000","repo":"neondatabase/neon","slug":"unexpected-status-code","errorCode":null,"errorMessage":"unexpected status code: {}","messagePattern":"unexpected status code: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pageserver/pagebench/src/cmd/getpage_latest_lsn.rs","lineNumber":691,"sourceCode":"        blks: Vec<u32>,\n    ) -> anyhow::Result<()> {\n        let req = page_api::GetPageRequest {\n            request_id: req_id.into(),\n            request_class: page_api::GetPageClass::Normal,\n            read_lsn: page_api::ReadLsn {\n                request_lsn: req_lsn,\n                not_modified_since_lsn: Some(mod_lsn),\n            },\n            rel,\n            block_numbers: blks,\n        };\n        self.req_tx.send(req).await?;\n        Ok(())\n    }\n\n    async fn recv_get_page(&mut self) -> anyhow::Result<(u64, Vec<Bytes>)> {\n        let resp = self.resp_rx.next().await.unwrap().unwrap();\n        anyhow::ensure!(\n            resp.status_code == page_api::GetPageStatusCode::Ok,\n            \"unexpected status code: {}\",\n            resp.status_code,\n        );\n        Ok((\n            resp.request_id.id,\n            resp.pages.into_iter().map(|p| p.image).collect(),\n        ))\n    }\n}\n\n/// A rich gRPC Pageserver client.\nstruct RichGrpcClient {\n    inner: Arc<client_grpc::PageserverClient>,\n    requests: FuturesUnordered<\n        Pin<Box<dyn Future<Output = anyhow::Result<page_api::GetPageResponse>> + Send>>,\n    >,\n}","sourceCodeStart":673,"sourceCodeEnd":709,"githubUrl":"https://github.com/neondatabase/neon/blob/8f60b04da47ffefe0e52bda2440134b42874eb75/pageserver/pagebench/src/cmd/getpage_latest_lsn.rs#L673-L709","documentation":"In the getpage_latest_lsn benchmark every GetPage reply must carry GetPageStatusCode::Ok, meaning a full page image. This ensure! fires when the pageserver answers with any other status (NotModified, BadRequest, InternalError, and so on), so the request/response pairing breaks and the bench aborts the worker.","triggerScenarios":"The bench requests pages for relations or LSNs the pageserver cannot serve as images: keys that do not exist at the requested LSN, data GC'd past the retention horizon, a sharded-tenant routing mismatch, or a page_api schema mismatch between the pagebench build and the running pageserver.","commonSituations":"Running pagebench from one neon commit against a pageserver built from another after GetPage protocol changes; benching a freshly created timeline before it has ingested WAL; requesting an LSN beyond the timeline end.","solutions":["Check the pageserver log at the failure timestamp for the concrete rejection reason","Rebuild or redeploy pagebench from the same commit as the pageserver so the page_api types match","Re-run timeline discovery and confirm the tenant is active with WAL beyond the requested LSNs","Reduce the bench to a single timeline to identify which target produces the non-Ok status"],"exampleFix":"// before\nanyhow::ensure!(\n    resp.status_code == page_api::GetPageStatusCode::Ok,\n    \"unexpected status code: {}\",\n    resp.status_code,\n);\n// after: distinguish statuses instead of treating all alike\nmatch resp.status_code {\n    page_api::GetPageStatusCode::Ok => {}\n    page_api::GetPageStatusCode::NotModified => {\n        // no image sent for this request; handle or skip explicitly\n    }\n    code => anyhow::bail!(\"unexpected status code: {code}\"),\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"fn is_ok_status(code: page_api::GetPageStatusCode) -> bool {\n    matches!(code, page_api::GetPageStatusCode::Ok)\n}","tryCatchPattern":"let (id, pages) = match client.recv_get_page().await {\n    Ok(v) => v,\n    Err(err) if err.to_string().starts_with(\"unexpected status code\") => {\n        // log worker context, drop this request, keep the bench running\n        tracing::warn!(?err, \"non-Ok GetPage status; skipping request\");\n        continue;\n    }\n    Err(err) => return Err(err),\n};","preventionTips":["Pin pagebench and pageserver to the same neon revision in bench environments","Warm up the timeline (ingest WAL) before measuring","Log the request LSN and relation alongside the failing status for triage"],"tags":["pagebench","page-api","getpage","status-code","grpc"],"backgroundTag":"unexpected-response-status-code","analyzedSha":"8f60b04da47ffefe0e52bda2440134b42874eb75","analyzedAt":"2026-08-16T23:39:28.135Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}