neondatabase/neon · critical
timeline id should be provided
Error message
timeline id should be provided
What it means
Neither spec.timeline_id nor the 'neon.timeline_id' GUC in cluster settings was present, so compute_ctl cannot identify which timeline the endpoint attaches to and aborts spec parsing. As with tenant id, this is the absence error; a malformed value produces the separate 'invalid timeline id' context error instead.
Source
Thrown at compute_tools/src/compute.rs:375
let storage_auth_token = spec.storage_auth_token.clone();
let tenant_id: TenantId = if let Some(tenant_id) = spec.tenant_id {
tenant_id
} else {
let guc = spec
.cluster
.settings
.find("neon.tenant_id")
.ok_or(anyhow::anyhow!("tenant id should be provided"))?;
TenantId::from_str(&guc).context("invalid tenant id")?
};
let timeline_id: TimelineId = if let Some(timeline_id) = spec.timeline_id {
timeline_id
} else {
let guc = spec
.cluster
.settings
.find("neon.timeline_id")
.ok_or(anyhow::anyhow!("timeline id should be provided"))?;
TimelineId::from_str(&guc).context(anyhow::anyhow!("invalid timeline id"))?
};
let endpoint_storage_addr: Option<String> = spec
.endpoint_storage_addr
.clone()
.or_else(|| spec.cluster.settings.find("neon.endpoint_storage_addr"));
let endpoint_storage_token = spec
.endpoint_storage_token
.clone()
.or_else(|| spec.cluster.settings.find("neon.endpoint_storage_token"));
let res = ParsedSpec {
spec,
pageserver_conninfo,
safekeeper_connstrings,
storage_auth_token,
tenant_id,View on GitHub (pinned to 8f60b04da4)
Solutions
- Set spec.timeline_id (preferred) or add "neon.timeline_id": "<32-hex-uuid>" to spec.cluster.settings
- Ensure the control plane stamps both tenant_id and timeline_id together when creating the spec
- Validate the spec has both ids (and both GUC fallbacks) before launch
Example fix
// before: neither field present -> error
// after
{ "timeline_id": "aa11bb22cc33dd44ee55ff6677889900", "cluster": { "settings": [ {"name": "neon.timeline_id", "value": "aa11bb22cc33dd44ee55ff6677889900" } ] } } Defensive patterns
Strategy: validation
Validate before calling
let timeline_ok = spec.timeline_id.is_some()
|| spec.cluster.settings.find("neon.timeline_id").map(|s| !s.trim().is_empty()).unwrap_or(false);
if !timeline_ok { anyhow::bail!("spec rejected: timeline id missing"); } Type guard
fn spec_has_timeline_id(spec: &ComputeSpec) -> bool {
spec.timeline_id.is_some() || spec.cluster.settings.find("neon.timeline_id").is_some()
} Prevention
- Generate tenant_id/timeline_id in one place and copy them into both the field and the GUC
- Validate UUID format (32 hex chars) at spec creation to also catch the sibling 'invalid timeline id' error
- Keep spec fixtures for tests covering both the field and the GUC fallback paths
When it happens
Trigger: ParsedSpec::try_from with spec.timeline_id == None and settings.find("neon.timeline_id") == None, immediately after the tenant_id lookup succeeds.
Common situations: Same family as the tenant_id error: hand-built specs, partial cplane migrations, version skew dropping the GUC, copy-paste specs where timeline_id was deleted.
Related errors
- pageserver connection information should be provided
- safekeeper connstrings should be provided
- tenant id should be provided
- shard {shard_index} missing from pageserver_connection_info
- Remote extensions are not configured
AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16).
Data as JSON: /api/errors/2e7d9c9da123f5f6.
Report an issue: GitHub.