{"record":{"id":"2e7d9c9da123f5f6","repo":"neondatabase/neon","slug":"timeline-id-should-be-provided","errorCode":null,"errorMessage":"timeline id should be provided","messagePattern":"timeline id should be provided","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"compute_tools/src/compute.rs","lineNumber":375,"sourceCode":"        let storage_auth_token = spec.storage_auth_token.clone();\n        let tenant_id: TenantId = if let Some(tenant_id) = spec.tenant_id {\n            tenant_id\n        } else {\n            let guc = spec\n                .cluster\n                .settings\n                .find(\"neon.tenant_id\")\n                .ok_or(anyhow::anyhow!(\"tenant id should be provided\"))?;\n            TenantId::from_str(&guc).context(\"invalid tenant id\")?\n        };\n        let timeline_id: TimelineId = if let Some(timeline_id) = spec.timeline_id {\n            timeline_id\n        } else {\n            let guc = spec\n                .cluster\n                .settings\n                .find(\"neon.timeline_id\")\n                .ok_or(anyhow::anyhow!(\"timeline id should be provided\"))?;\n            TimelineId::from_str(&guc).context(anyhow::anyhow!(\"invalid timeline id\"))?\n        };\n\n        let endpoint_storage_addr: Option<String> = spec\n            .endpoint_storage_addr\n            .clone()\n            .or_else(|| spec.cluster.settings.find(\"neon.endpoint_storage_addr\"));\n        let endpoint_storage_token = spec\n            .endpoint_storage_token\n            .clone()\n            .or_else(|| spec.cluster.settings.find(\"neon.endpoint_storage_token\"));\n\n        let res = ParsedSpec {\n            spec,\n            pageserver_conninfo,\n            safekeeper_connstrings,\n            storage_auth_token,\n            tenant_id,","sourceCodeStart":357,"sourceCodeEnd":393,"githubUrl":"https://github.com/neondatabase/neon/blob/8f60b04da47ffefe0e52bda2440134b42874eb75/compute_tools/src/compute.rs#L357-L393","documentation":"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.","triggerScenarios":"ParsedSpec::try_from with spec.timeline_id == None and settings.find(\"neon.timeline_id\") == None, immediately after the tenant_id lookup succeeds.","commonSituations":"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.","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"],"exampleFix":"// before: neither field present -> error\n// after\n{ \"timeline_id\": \"aa11bb22cc33dd44ee55ff6677889900\", \"cluster\": { \"settings\": [ {\"name\": \"neon.timeline_id\", \"value\": \"aa11bb22cc33dd44ee55ff6677889900\" } ] } }","handlingStrategy":"validation","validationCode":"let timeline_ok = spec.timeline_id.is_some()\n    || spec.cluster.settings.find(\"neon.timeline_id\").map(|s| !s.trim().is_empty()).unwrap_or(false);\nif !timeline_ok { anyhow::bail!(\"spec rejected: timeline id missing\"); }","typeGuard":"fn spec_has_timeline_id(spec: &ComputeSpec) -> bool {\n    spec.timeline_id.is_some() || spec.cluster.settings.find(\"neon.timeline_id\").is_some()\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["rust","compute-ctl","spec","configuration","timeline-id","startup"],"backgroundTag":"missing-configuration","analyzedSha":"8f60b04da47ffefe0e52bda2440134b42874eb75","analyzedAt":"2026-08-16T23:39:28.135Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}