{"record":{"id":"d7136f2aebb25c14","repo":"neondatabase/neon","slug":"only-unsharded-tenants-are-supported-at-this-time","errorCode":null,"errorMessage":"only unsharded tenants are supported at this time: {}","messagePattern":"only unsharded tenants are supported at this time: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pageserver/client/src/mgmt_api/util.rs","lineNumber":21,"sourceCode":"use std::sync::Arc;\n\nuse pageserver_api::shard::TenantShardId;\nuse tokio::task::JoinSet;\nuse utils::id::{TenantId, TenantTimelineId};\n\nuse super::Client;\n\n/// Retrieve a list of all of the pageserver's timelines.\n///\n/// Fails if there are sharded tenants present on the pageserver.\npub async fn get_pageserver_tenant_timelines_unsharded(\n    api_client: &Arc<Client>,\n) -> anyhow::Result<Vec<TenantTimelineId>> {\n    let mut timelines: Vec<TenantTimelineId> = Vec::new();\n    let mut tenants: Vec<TenantId> = Vec::new();\n    for ti in api_client.list_tenants().await? {\n        if !ti.id.is_unsharded() {\n            anyhow::bail!(\n                \"only unsharded tenants are supported at this time: {}\",\n                ti.id\n            );\n        }\n        tenants.push(ti.id.tenant_id)\n    }\n    let mut js = JoinSet::new();\n    for tenant_id in tenants {\n        js.spawn({\n            let mgmt_api_client = Arc::clone(api_client);\n            async move {\n                (\n                    tenant_id,\n                    mgmt_api_client\n                        .tenant_details(TenantShardId::unsharded(tenant_id))\n                        .await\n                        .unwrap(),\n                )","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/neondatabase/neon/blob/8f60b04da47ffefe0e52bda2440134b42874eb75/pageserver/client/src/mgmt_api/util.rs#L3-L39","documentation":"`get_pageserver_tenant_timelines_unsharded` is a mgmt-api convenience helper that lists every timeline on a pageserver and fails fast if any tenant is sharded. It exists for callers that can only reason about unsharded tenants; encountering a `TenantShardId` with a shard count means the helper's precondition is violated.","triggerScenarios":"Calling `get_pageserver_tenant_timelines_unsharded(api_client)` against a pageserver that hosts at least one tenant whose `TenantShardId` reports a non-zero shard count (e.g. after the tenant was split into shards).","commonSituations":"Running legacy tooling or scripts against a pageserver after sharding was enabled for some tenants; control scripts written before sharding existed; test fixtures accidentally creating sharded tenants.","solutions":["Switch the caller to a shard-aware listing (iterate shards via the mgmt API per TenantShardId) instead of the unsharded helper","Or only point the helper at pageservers guaranteed to host unsharded tenants exclusively","Identify the sharded tenant from the error message and handle its shards separately","If sharding was unintentional, investigate how the tenant got sharded before proceeding"],"exampleFix":"// before: fails if any tenant is sharded\nlet timelines = get_pageserver_tenant_timelines_unsharded(&client).await?;\n\n// after: shard-aware listing\nfor ti in client.list_tenants().await? {\n    if ti.id.is_unsharded() {\n        // handle unsharded tenant timelines\n    } else {\n        // handle sharded tenant via its shard ids\n    }\n}","handlingStrategy":"validation","validationCode":"for ti in api_client.list_tenants().await? {\n    if !ti.id.is_unsharded() {\n        // handle or reject sharded tenants before using the unsharded-only helper\n        anyhow::bail!(\"sharded tenant {} present; use shard-aware listing\", ti.id);\n    }\n}","typeGuard":"fn all_unsharded(tenants: &[TenantInfo]) -> bool {\n    tenants.iter().all(|ti| ti.id.is_unsharded())\n}","tryCatchPattern":null,"preventionTips":["Prefer shard-aware APIs in any environment where sharding may be enabled","Gate unsharded-only helpers behind an environment check on pageserver tenant state","Document which scripts/tools assume unsharded tenants and monitor for shard creation"],"tags":["rust","neon","pageserver","sharding","mgmt-api"],"backgroundTag":"sharded-tenant-unsupported","analyzedSha":"8f60b04da47ffefe0e52bda2440134b42874eb75","analyzedAt":"2026-08-16T23:39:28.135Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}