{"record":{"id":"9cfbd0e923705392","repo":"xai-org/grok-build","slug":"timed-out-waiting-s-for-git-object-database-perm","errorCode":null,"errorMessage":"timed out waiting {}s for git object database permit","messagePattern":"timed out waiting (.+?)s for git object database permit","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-workspace/src/git_odb.rs","lineNumber":67,"sourceCode":"    pub fn new(permits: usize, acquire_wait: Duration) -> Self {\n        Self {\n            inner: Arc::new(OdbLimiterInner {\n                sem: Arc::new(Semaphore::new(permits.max(1))),\n                acquire_wait,\n            }),\n        }\n    }\n\n    pub async fn acquire(&self) -> Result<OdbPermit> {\n        match tokio::time::timeout(\n            self.inner.acquire_wait,\n            self.inner.sem.clone().acquire_owned(),\n        )\n        .await\n        {\n            Ok(Ok(permit)) => Ok(OdbPermit { _permit: permit }),\n            Ok(Err(_)) => Err(anyhow!(\"git object database semaphore closed\")),\n            Err(_) => Err(anyhow!(\n                \"timed out waiting {}s for git object database permit\",\n                self.inner.acquire_wait.as_secs()\n            )),\n        }\n    }\n\n    pub fn try_acquire(&self) -> Option<OdbPermit> {\n        self.inner\n            .sem\n            .clone()\n            .try_acquire_owned()\n            .ok()\n            .map(|permit| OdbPermit { _permit: permit })\n    }\n}\n\n#[cfg(test)]\nmod tests {","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-workspace/src/git_odb.rs#L49-L85","documentation":"OdbHandle::acquire bounded-waits for a permit on the git object database's concurrency-limiting semaphore using the configured acquire_wait duration. When the future times out (tokio::time::timeout elapsed), this error is returned, including the wait duration in seconds. It indicates the object database is saturated with concurrent users.","triggerScenarios":"Calling acquire when the number of concurrent permit holders has reached the semaphore capacity for longer than acquire_wait — e.g. many parallel git object reads (large history scans, batch operations) all holding permits.","commonSituations":"Large repos with many simultaneous file-history or blame queries; long-running operations holding permits while others queue; acquire_wait configured too small for the workload; a leaked permit path keeping capacity occupied.","solutions":["Increase the acquire_wait timeout configuration to tolerate queueing.","Reduce concurrency of callers doing git object reads (batch/serialize heavy scans).","Investigate permit leaks — operations that hold permits longer than expected or never release them on early-return paths.","Retry with backoff; the saturation is often transient."],"exampleFix":"// before: default (too short) wait under heavy load\nlet permit = odb.acquire().await?;\n// after: raise the wait budget\nlet odb = odb.with_acquire_wait(Duration::from_secs(60));\nlet permit = odb.acquire().await?;","handlingStrategy":"retry","validationCode":"let in_flight = odb.permits_in_use();\nif in_flight >= odb.capacity() {\n    anyhow::bail!(\"git odb saturated ({in_flight}/{}) — reduce concurrency first\", odb.capacity());\n}","typeGuard":null,"tryCatchPattern":"let permit = loop {\n    match odb.acquire().await {\n        Ok(p) => break Ok(p),\n        Err(e) if e.to_string().contains(\"timed out\") => {\n            backoff.wait();\n            if backoff.exhausted() { break Err(e); }\n        }\n        Err(e) => break Err(e),\n    }\n}?;","preventionTips":["Configure acquire_wait generously for large-repo batch workloads","Limit parallel git object readers to the semaphore capacity","Hold permits for the shortest possible scope (drop immediately after the read)","Watch for leaked permits via metrics/logging in early-return paths"],"tags":["semaphore","timeout","git-odb","concurrency"],"backgroundTag":"acquire-timeout","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}