{"record":{"id":"64bfe4c886957f34","repo":"xai-org/grok-build","slug":"git-object-database-semaphore-closed","errorCode":null,"errorMessage":"git object database semaphore closed","messagePattern":"git object database semaphore closed","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-workspace/src/git_odb.rs","lineNumber":66,"sourceCode":"    #[must_use]\n    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)]","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-workspace/src/git_odb.rs#L48-L84","documentation":"OdbHandle::acquire waits, up to a configured timeout, for a permit on a global semaphore that limits concurrent access to the git object database. The Tokio semaphore's acquire_owned() returned Err(Closed), meaning the semaphore has been permanently shut down (all handles closed / dropped by the runtime teardown). This is an invariant violation, not a capacity issue.","triggerScenarios":"Calling acquire (directly or through workspace/odb operations) after the owning structure was shut down and its semaphore was closed — e.g. acquiring a permit during process/runtime shutdown, or using an OdbHandle whose shared inner state was closed elsewhere.","commonSituations":"Background tasks outliving the workspace and trying to read git objects during shutdown; calling acquire on a handle after close/shutdown was invoked; spawn-then-drop ordering bugs in tests.","solutions":["Ensure all git-odb work is complete and tasks joined before shutting down the workspace/runtime.","Do not call acquire after the owning component has been closed; check lifecycle ordering.","If you control shutdown, drop pending acquirers before closing the semaphore.","Re-create the handle/workspace rather than reusing a closed one."],"exampleFix":"// before: task keeps acquiring after shutdown\nlet handle = tokio::spawn(async move { odb.acquire().await?.read_commit(oid).await });\ndrop(workspace); // closes semaphore\n// after\nlet handle = tokio::spawn(async move { odb.acquire().await?.read_commit(oid).await });\nlet _ = handle.await; // join before dropping workspace\n drop(workspace);","handlingStrategy":"try-catch","validationCode":"// Check lifecycle before acquiring\nif workspace.is_shutdown() {\n    anyhow::bail!(\"workspace already shut down; git odb unavailable\");\n}","typeGuard":null,"tryCatchPattern":"match odb.acquire().await {\n    Ok(permit) => { /* use permit */ }\n    Err(e) if e.to_string() == \"git object database semaphore closed\" => {\n        eprintln!(\"odb shut down; aborting work gracefully\");\n        // stop background work, do not retry\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Join all background tasks before dropping/shutting down the workspace","Never spawn tasks holding an OdbHandle that can outlive the handle","Treat semaphore-closed as terminal: do not retry, fix shutdown ordering"],"tags":["semaphore","shutdown","git-odb","concurrency"],"backgroundTag":"semaphore-closed","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}