{"record":{"id":"1f7fb002692177e2","repo":"xtekky/gpt4free","slug":"lock-timeout","errorCode":"LOCK_TIMEOUT","errorMessage":"Failed to acquire lock","messagePattern":"Failed to acquire lock","errorType":"exception","errorClass":"TokenManagerError","httpStatus":null,"severity":"error","filePath":"g4f/Provider/qwen/sharedTokenManager.py","lineNumber":246,"sourceCode":"\n        for _ in range(max_attempts):\n            try:\n                with open(lock_path, \"w\") as f:\n                    f.write(lock_id)\n                return\n            except Exception:\n                try:\n                    stat = os.stat(str(lock_path))\n                    lock_age = int(time.time() * 1000) - int(stat.st_mtime * 1000)\n                    if lock_age > LOCK_TIMEOUT_MS:\n                        try:\n                            await os.unlink(str(lock_path))\n                        except Exception:\n                            pass\n                except Exception:\n                    pass\n                await asyncio.sleep(attempt_interval / 1000)\n        raise TokenManagerError(TokenError.LOCK_TIMEOUT, \"Failed to acquire lock\")\n\n    async def releaseLock(self, lock_path: Path):\n        try:\n            await os.unlink(str(lock_path))\n        except Exception:\n            pass\n\n    async def saveCredentialsToFile(self, credentials: dict):\n        file_path = self.getCredentialFilePath()\n        os.makedirs(file_path.parent, exist_ok=True)\n        with open(file_path, \"w\") as f:\n            f.write(json.dumps(credentials, indent=2))\n        stat = os.stat(str(file_path))\n        self.memory_cache[\"file_mod_time\"] = int(stat.st_mtime * 1000)\n\n    def isTokenValid(self, credentials: dict) -> bool:\n        expiry_date = credentials.get(\"expiry_date\")\n        if not expiry_date:","sourceCodeStart":228,"sourceCodeEnd":264,"githubUrl":"https://github.com/xtekky/gpt4free/blob/973504e1770928ed5fb82f43da528f441ad9ddc3/g4f/Provider/qwen/sharedTokenManager.py#L228-L264","documentation":"TokenManagerError LOCK_TIMEOUT raised by SharedTokenManager.acquireLock (sharedTokenManager.py:246) after exhausting all attempts to create the lock file guarding credential refresh. The loop even includes stale-lock recovery — if the lock's mtime exceeds LOCK_TIMEOUT_MS it unlinks it — so this error means the lock was repeatedly recreated by a live holder or could not be removed (permissions).","triggerScenarios":"Another process/thread holds the lock file and keeps touching it longer than the total retry window; lock removal fails due to directory permissions; many g4f processes sharing one credentials file on a slow or network filesystem where mtime updates lag.","commonSituations":"Running several g4f workers against the same home directory; a crashed process left a lock on a filesystem where mtime doesn't advance (some network mounts); NFS latency making the stale detection ineffective.","solutions":["Find and stop the process holding the lock (lsof / fuser on the lock path), or delete the stale lock file manually","Reduce concurrent workers sharing one credentials file, or give each its own config dir","On network filesystems, move the credentials dir to local disk","Retry after the holder finishes — transient contention resolves itself"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"from pathlib import Path\nimport time\n\ndef lock_is_stale(path, max_age_ms) -> bool:\n    try:\n        age_ms = time.time() * 1000 - Path(path).stat().st_mtime * 1000\n        return age_ms > max_age_ms\n    except OSError:\n        return True","typeGuard":null,"tryCatchPattern":"try:\n    creds = await manager.getValidCredentials(qwen_client)\nexcept TokenManagerError as e:\n    if \"Failed to acquire lock\" in str(e.message):\n        await asyncio.sleep(2)\n        creds = await manager.getValidCredentials(qwen_client)  # holder likely finished\n    else:\n        raise","preventionTips":["Limit concurrent processes sharing one credentials file — one refresher at a time","Keep the credentials directory on local disk, not NFS","Clean up stale lock files when processes crash (startup hygiene)"],"tags":["qwen","token-manager","file-lock","concurrency"],"backgroundTag":null,"analyzedSha":"973504e1770928ed5fb82f43da528f441ad9ddc3","analyzedAt":"2026-08-14T23:45:32.408Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}