The New version of Cursor CLI won't run on RHEL8

Describe the Bug

The new version of Cursor CLI/cursor-agent, 2025.08.15-dbc8d73, crashes when run on RHEL8 (and presumably many other slightly older distros) due to a requirement for GLIBC 2.29.

Error: Failed to load native binding for linux/x64 (expected: ./merkle-tree-napi.linux-x64-gnu.node)
Original error: Error: /lib64/libm.so.6: version `GLIBC_2.29’ not found (required by /

Steps to Reproduce

Run the cursor-agent command on a system with GLIBC 2.28 or older

Expected Behavior

cursor-cli should work as intended. GLIBC should be backwards compatible, especially 2.28. RHEL8 is not EoL until 2029.

Operating System

Linux

Current Cursor Version (Menu → About Cursor → Copy)

Version: cursor-agent 2025.08.15-dbc8d73
VSCode version: N/A

Does this stop you from using Cursor

Yes - Cursor is unusable

Hey, thanks for the report, we’ll look into it.

1 Like

This is still broken and unusable on RHEL8

Any news on this bug ? Can’t use it !

Hey, are you using the latest version of Cursor CLI?

Yes, installed this morning, and retried it now using the command line

curl https://cursor.com/install -fsS | bash

Original error: Error: /lib64/libm.so.6: version `GLIBC_2.29’ not found (required by /home/***/.local/share/cursor-agent/versions/2025.09.04-fc40cd1/a3h1d327.node)

Rocky Linux release 8.7 (Green Obsidian)
NAME=“Rocky Linux”
VERSION=“8.7 (Green Obsidian)”
ID=“rocky”
ID_LIKE=“rhel centos fedora”
VERSION_ID=“8.7”

1 Like

Nope, no movement on this. I’ve upgraded it a bunch. The only way I can use cursor is to stick with the version from 2025.08.09. Anything newer than that has been compiled against the newer glibc and won’t run. This is likely a CI/CD problem since I seriously doubt cursor-agent is doing anything that actually needs the newest version of glibc

1 Like

Just tried today as well, no joy. Issue is still there.

Just confirming that the CLI currently has a minimum requirement of GLIBC-2.29. Should probably cross-post with the similar closed issue: start-cursor-errror-version-glibc-2-29-not-found

The solution - as is always the case with glibc - is to install and run from a container. Otherwise, need devs to either a) allow build from source or b) release a version recompiled on 2.28.

1 Like
~ $ cursor-agent
file:///root/.local/share/cursor-agent/versions/2025.09.12-4852336/index-tqajwqmd.js:2
Original error: ${s&&s.stack?s.stack:s}`;throw new Error(A)}b.exports=E;b.exports.MerkleClient=E.MerkleClient;b.exports.MULTI_ROOT_ABSOLUTE_PATH=E.MULTI_ROOT_ABSOLUTE_PATH});import*as o from"crypto";var Y="aes-256-ctr",k=6,z="\x00",P=/([./\\])/;function B$(H){let $=(4-H.length%4)%4;return H+z.repeat($)}function E$(H){return H.replace(new RegExp(`${z}+$`),"")}function l$(H){let $=o.createHash("sha256").update(H).update(Buffer.from([0])).digest(),L=o.createHash("sha256").update(H).update(Buffer.from([1])).digest();return{macKey:$,encKey:L}}class T${masterKeyRaw;macKey;encKey;constructor(H){this.masterKeyRaw=H;let $=Buffer.from(H,"base64url"),{macKey:L,encKey:A}=l$($);this.macKey=L,this.encKey=A}exportKey(){return this.masterKeyRaw}encrypt(H){let $=o.createHmac("sha256",this.macKey);$.update(H);let L=$.digest().subarray(0,k),A=Buffer.concat([L,Buffer.alloc(10)]),t=o.createCipheriv(Y,this.encKey,A),I=t.update(B$(H),"utf8","base64url");return I+=t.final("base64url"),Buffer.concat([L,Buffer.from(I,"base64url")]).toString("base64url")}decrypt(H){let $=Buffer.from(H,"base64url"),L=$.subarray(0,k),A=Buffer.concat([L,Buffer.alloc(10)]),t=$.subarray(k).toString("base64url"),I=o.createDecipheriv(Y,this.encKey,A),D=I.update(t,"base64url","utf8");return D+=I.final("utf8"),E$(D)}}function l(H,$){return H.split(P).map((L)=>{if(P.test(L))return L;if(L==="")return L;return $.encrypt(L)}).join("")}function Z(H,$){return H.split(P).map((L)=>{if(P.test(L))return L;if(L==="")return L;return $.decrypt(L)}).join("")}var Q=i(G(),1),EH=i(LH(),1);import*as lH from"crypto";class d extends Error{constructor(H="AsyncQueue is closed"){super(H);this.name="AsyncQueueClosedError"}}class V{items=[];pendingPops=[];isClosed=!1;closeError;push(...H){for(let $ of H)this.pushSingle($)}pushSingle(H){if(this.isClosed)throw this.closeError??new d;let $=this.pendingPops.shift();if($!==void 0){if($.onAbort!==void 0)try{$.onAbort()}catch{}let L=$.batcher.createBatch(H);$.resolve(L);return}this.items.push(H)}pop(H,$){if(this.items.length>0){let A=this.items.shift(),t=H.createBatch(A);while(this.items.length>0){let I=this.items[0];if(t.add(I))this.items.shift();else break}return Promise.resolve(t)}if(this.isClosed)return Promise.reject(this.closeError??new d);let L=$?.signal;if(L!==void 0&&L.aborted)return Promise.reject(L.reason??new Error("Aborted"));return new Promise((A,t)=>{let I={resolve:A,reject:t,batcher:H};if(L!==void 0){let D=()=>{let e=this.pendingPops.indexOf(I);if(e!==-1)this.pendingPops.splice(e,1);t(L.reason??new Error("Aborted"))};I.onAbort=()=>{try{L.removeEventListener("abort",D)}catch{}};try{L.addEventListener("abort",D,{once:!0})}catch{}}this.pendingPops.push(I)})}tryPop(){return this.items.shift()}get size(){return this.items.length}get waiting(){return this.pendingPops.length}isEmpty(){return this.items.length===0}drain(H){let $=H===void 0||H>=this.items.length?this.items.length:H;if($===0)return[];return this.items.splice(0,$)}close(H){if(this.isClosed)return;this.isClosed=!0,this.closeError=H??new d;while(this.pendingPops.length>0){let $=this.pendingPops.shift();if($===void 0)break;if($.onAbort!==void 0)try{$.onAbort()}catch{}$.reject(this.closeError)}}createConsumer(H){return new AH(this,H)}}class AH{queue;batcher;constructor(H,$){this.queue=H,this.batcher=$}async*[Symbol.asyncIterator](){while(!0)try{yield await this.queue.pop(this.batcher)}catch(H){if(H instanceof d)return;throw H}}}class tH{maxSize;constructor(H,$=[]){this.maxSize=H,this.items=$}items;size=1;add(H){if(this.size>=this.maxSize)return!1;return this.items.push(H),this.size++,!0}}class X{maxSize;constructor(H){this.maxSize=H}createBatch(H){return new tH(this.maxSize,[H])}}import*as DH from"crypto";import*as fH from"fs/promises";import d$ from"path";var IH=i(G(),1);var p$=IH.createLogger("@anysphere/indexing-client:sync");class x{relativePath;constructor(H){this.relativePath=H}}class m{encryptedRelativePath;constructor(H){this.encryptedRelativePath=H}}async function W(H,$,L,A,t){p$.info(H,"Syncing merkle subtree",{path:L.getRelativePath(),localHash:L.getHash(),remoteHash:A?.getHash()});let I=new Map;if(A!==void 0&&L!==void 0){let f=L.getHash(),a=A.getHash();if(a!==void 0&&a===f)return[];let u=await A.diffNode(f);if(u.type==="match")return[];if(u.type!=="mismatch")throw new Error("Unknown response type");for(let c of u.children)I.set(c.getRelativePath(),c)}if(L.getType()==="file")return t.push(new x(L.getRelativePath())),[];let D=[],e=new Set;for(let f of L.getChildren()){let a=l(f.getRelativePath(),$),u=I.get(a);D.push([f,u]),e.add(a)}for(let[f,a]of I)if(!e.has(f))t.push(new m(f));return D}import y from"path";function v(H){let $=[],L=y.normalize(H),A=y.dirname(L);while(!0){if($.push({relativeWorkspacePath:A,hashOfNode:""}),A===".")break;A=y.dirname(A)}return $}var rH=i(G(),1);var eH=rH.createLogger("@anysphere/indexing-client:changeWorker");async function aH(H,$,L,A,t){let I=[];for(let e of L.items)if(e instanceof x){eH.info(H,"Applying change",{type:"add",relativePath:e.relativePath});let f=d$.join(A,e.relativePath),a=fH.readFile(f,"utf-8"),u=l(e.relativePath,$);I.push(a.then((c)=>({updateType:M.ADD,ancestorSpline:v(u),partialPath:{case:"localFile",value:{unencryptedRelativeWorkspacePath:e.relativePath,hash:DH.createHash("sha256").update(c).digest("hex"),file:{relativeWorkspacePath:u,contents:c}}}})))}else if(e instanceof m)I.push(Promise.resolve({updateType:M.DELETE,ancestorSpline:v(e.encryptedRelativePath),partialPath:{case:"directory",value:{relativeWorkspacePath:e.encryptedRelativePath}}}));else throw new Error("Unknown change type");let D=await Promise.all(I);for(let e of D)eH.info(H,"Updating file",e);await t(H,D)}async function uH(H,$,L,A){for await(let t of $.createConsumer(A))await L(H,t)}class N{client;codebaseId;path;hash;constructor(H,$,L,A=""){this.client=H,this.codebaseId=$,this.path=L,this.hash=A}getHash(){return this.hash}async diffNode(H){let $=await this.client.syncMerkleSubtreeV2({codebaseId:this.codebaseId,localPartialPath:{relativeWorkspacePath:this.path,hashOfNode:H}});if($.result.case==="match")return{type:"match"};else if($.result.case==="mismatch")return{type:"mismatch",children:$.result.value.children.map((L)=>{return new N(this.client,this.codebaseId,L.relativeWorkspacePath,L.hashOfNode)})};else throw new Error("Unknown response type")}getRelativePath(){return this.path}}class g{fileInfo;constructor(H){this.fileInfo=H}getRelativePath(){let H=this.fileInfo.unencryptedRelativePath;if(H.length===0)return".";return H}getHash(){return this.fileInfo.hash}getChildren(){return this.fileInfo.children?.map((H)=>new g(H))??[]}getType(){return this.fileInfo.children===void 0?"file":"directory"}}var _H=i(G(),1);import{randomUUID as M$}from"crypto";var K=_H.createLogger("@anysphere/indexing-client:updater");function oH(H,$,L){return async(A,t)=>{let I=M$();K.info(A,"Updating files",{requestId:I,changes:t.length});try{let D=await H.fastUpdateFileV2({codebaseId:L,clientRepositoryInfo:$,updateType:M.BATCH,fileUpdates:t},{headers:{"x-request-id":I}});K.info(A,"Updated files",{requestId:I,response:D.toJson()})}catch(D){throw K.error(A,"Error updating files",{requestId:I,error:D}),D}}}class O{permits;waitingResolvers=[];constructor(H){if(!Number.isInteger(H)||H<0)throw new Error("Semaphore requires a non-negative integer number of permits");this.permits=H}async acquire(){if(this.permits>0)return this.permits-=1,Promise.resolve();return new Promise((H)=>{this.waitingResolvers.push(H)})}release(){let H=this.waitingResolvers.shift();if(H!==void 0)H();else this.permits+=1}}class J{work=[];semaphore;constructor(H){this.semaphore=new O(H)}async addTask(H){await this.semaphore.acquire();let L=(async()=>{try{return await H()}finally{this.semaphore.release()}})();this.work.push(L)}async next(){if(this.work.length===0)return;let[H,$]=await Promise.race(this.work.map((L,A)=>L.then((t)=>[t,A])));return this.work.splice($,1),H}async*[Symbol.asyncIterator](){while(!0){let H=await this.next();if(H===void 0)return;yield H}}}import{randomUUID as n$}from"crypto";var cH=Q.createLogger("@anysphere/indexing-client:client");function h$(H,$){return Object.values(H).sort((L,A)=>L.localeCompare(A)).map((L)=>l(L,$)).join(",")}function P$(H){return lH.createHash("sha256").update(H+"_PATH_KEY_HASH_SHA256").digest("hex")}async function C$(H,$,L,A,t,I,D){let e=new g(t),f=new J(64),a=new V,u=new N($,I,".");await f.addTask(()=>W(H,L,e,u,a));let c=oH($,A,I),_=Array.from({length:8},()=>uH(H,a,(w,U)=>aH(w,L,U,D,c),new X(32))),h=async()=>{try{for await(let w of f)for(let[U,c$]of w)await f.addTask(()=>W(H,L,U,c$,a))}finally{a.close()}},T=async()=>{await Promise.all(_)};await Promise.all([h(),T()])}async function b$(H){for await(let $ of H)return $;throw new Error("No element found")}function G$(H){return`file://${H}`}class TH{client;clientRepositoryInfo;repositoryIdentityProvider;workspacePath;constructor(H,$,L,A){this.client=H,this.clientRepositoryInfo=$,this.repositoryIdentityProvider=L,this.workspacePath=A}async createRepositoryInfo(H,$){return{isLocal:!0,numFiles:$,isTracked:!1,remoteNames:[],remoteUrls:[],workspaceUri:h$({"":G$(this.workspacePath)},H.encryptionScheme),repoName:H.repoName,repoOwner:H.repoOwner}}async index(H){let $=await this.repositoryIdentityProvider.loadRepositoryIdentity(),L=new EH.MerkleClient({"":this.workspacePath});await L.build(!1,{maxNumFiles:1e4}),cH.info(H,"Getting tree structure for",{workspacePath:this.workspacePath});let[A,t,I]=await Promise.all([L.getTreeStructure(),L.getSimhash(),L.getNumEmbeddableFiles()]);if(A===null)throw new Error("Tree structure is null");let D=$.encryptionScheme,e=P$(D.exportKey()),f=new F({repository:await this.createRepositoryInfo($,I),rootHash:A.hash,similarityMetricType:S.SIMHASH,similarityMetric:Array.from(t),pathKeyHash:e,pathKeyHashType:R.SHA256,doCopy:!1,returnAfterBackgroundCopyStarted:!1,pathKey:"",localCodebaseRootInfo:void 0}),u=(await this.client.fastRepoInitHandshakeV2(f)).codebases.map(async(_)=>{if(_.status===BH.UP_TO_DATE)return{codebaseId:_.codebaseId,status:n.SUCCESS,hasUpdates:!1};try{return await C$(H,this.client,D,this.clientRepositoryInfo,A,_.codebaseId,this.workspacePath),{codebaseId:_.codebaseId,status:n.SUCCESS,hasUpdates:!0}}catch(h){return cH.error(H,"Error syncing codebase",{codebaseId:_.codebaseId,error:h}),{codebaseId:_.codebaseId,status:n.FAILURE,hasUpdates:!1}}}),c=await Promise.all(u);await this.client.fastRepoSyncComplete({codebases:c.map(({codebaseId:_,status:h,hasUpdates:T})=>{return{codebaseId:_,status:n.SUCCESS,hasUpdates:T,similarityMetricType:T?S.SIMHASH:S.UNSPECIFIED,similarityMetric:T?Array.from(t):[],pathKeyHash:e,pathKeyHashType:R.SHA256}})})}}class x${client;clientRepositoryInfo;repositoryIdentityProvider;workspacePath;constructor(H,$,L,A){this.client=H,this.clientRepositoryInfo=$,this.repositoryIdentityProvider=L,this.workspacePath=A}createIndexer(){return new TH(this.client,this.clientRepositoryInfo,this.repositoryIdentityProvider,this.workspacePath)}async createFastRepositoryInfo(){let H=await this.repositoryIdentityProvider.loadRepositoryIdentity();return{relativeWorkspacePath:".",repoName:H.repoName,repoOwner:H.repoOwner,orthogonalTransformSeed:0}}async decryptPath(H,$){let A=(await this.repositoryIdentityProvider.loadRepositoryIdentity()).encryptionScheme;return Z($,A)}async getPathEncryptionKey(H){return(await this.repositoryIdentityProvider.loadRepositoryIdentity()).encryptionScheme.exportKey()}async search(H,$){let A=(await this.repositoryIdentityProvider.loadRepositoryIdentity()).encryptionScheme,t=n$();console.log(t);let I=await this.client.semSearchFast({request:{query:$,repository:await this.createFastRepositoryInfo(),topK:16}}),e=(await b$(I)).response?.codeResults;if(e===void 0)return;return e.map((f)=>{return{...f,codeBlock:f.codeBlock?{...f.codeBlock,relativeWorkspacePath:Z(f.codeBlock.relativeWorkspacePath,A)}:void 0}})}}var a$={typeName:"aiserver.v1.RepositoryService",methods:{fastRepoInitHandshake:{name:"FastRepoInitHandshake",I:MH,O:nH,kind:r.Unary},syncMerkleSubtree:{name:"SyncMerkleSubtree",I:bH,O:GH,kind:r.Unary},fastUpdateFile:{name:"FastUpdateFile",I:NH,O:gH,kind:r.Unary},searchRepositoryV2:{name:"SearchRepositoryV2",I:OH,O:JH,kind:r.Unary},removeRepositoryV2:{name:"RemoveRepositoryV2",I:vH,O:KH,kind:r.Unary},fastRepoInitHandshakeV2:{name:"FastRepoInitHandshakeV2",I:F,O:hH,kind:r.Unary},syncMerkleSubtreeV2:{name:"SyncMerkleSubtreeV2",I:xH,O:mH,kind:r.Unary},fastUpdateFileV2:{name:"FastUpdateFileV2",I:SH,O:FH,kind:r.Unary},fastRepoSyncComplete:{name:"FastRepoSyncComplete",I:PH,O:CH,kind:r.Unary},semSearchFast:{name:"SemSearchFast",I:j,O:q,kind:r.ServerStreaming},semSearch:{name:"SemSearch",I:j,O:q,kind:r.ServerStreaming},ensureIndexCreated:{name:"EnsureIndexCreated",I:dH,O:iH,kind:r.Unary},getHighLevelFolderDescription:{name:"GetHighLevelFolderDescription",I:sH,O:pH,kind:r.Unary},getEmbeddings:{name:"GetEmbeddings",I:WH,O:yH,kind:r.Unary},getUploadLimits:{name:"GetUploadLimits",I:wH,O:UH,kind:r.Unary},getNumFilesToSend:{name:"GetNumFilesToSend",I:kH,O:ZH,kind:r.Unary},getAvailableChunkingStrategies:{name:"GetAvailableChunkingStrategies",I:VH,O:XH,kind:r.Unary},getLineNumberClassifications:{name:"GetLineNumberClassifications",I:RH,O:QH,kind:r.ServerStreaming},getCopyStatus:{name:"GetCopyStatus",I:jH,O:qH,kind:r.Unary}}},TL={typeName:"aiserver.v1.GitIndexService",methods:{repoHistoryInitHandshake:{name:"RepoHistoryInitHandshake",I:YH,O:zH,kind:r.Unary},repoHistorySyncOne:{name:"RepoHistorySyncOne",I:H$,O:$$,kind:r.Unary},repoHistorySyncComplete:{name:"RepoHistorySyncComplete",I:L$,O:A$,kind:r.Unary},removeRepoHistory:{name:"RemoveRepoHistory",I:e$,O:D$,kind:r.Unary},searchPRHistory:{name:"SearchPRHistory",I:t$,O:I$,kind:r.Unary},getPRIndexingStatus:{name:"GetPRIndexingStatus",I:f$,O:r$,kind:r.Unary}}};class o${items;index;constructor(H){this.items=H,this.index=0}next(){let H=this.items[this.index];return this.index=(this.index+1)%this.items.length,H}}function m$(H){let $=new o$(H);return{unary:(L,A,t,I,D,e,f)=>{return $.next().unary(L,A,t,I,D,e,f)},stream:(L,A,t,I,D,e,f)=>{return $.next().stream(L,A,t,I,D,e,f)}}}function N$(H,$){let L=[];for(let A=0;A<$;A++)L.push(H());return m$(L)}function g$(H,$){let L=H(),A=0;return{unary:(t,I,D,e,f,a,u)=>{if(A++,A>$)L=H(),A=0;return L.unary(t,I,D,e,f,a,u)},stream:(t,I,D,e,f,a,u)=>{if(A++,A>$)L=H(),A=0;return L.stream(t,I,D,e,f,a,u)}}}function ML(H){let $=()=>_$({baseUrl:H.endpoint,httpVersion:H.httpVersion??"2",interceptors:H.interceptors,nodeOptions:H.endpoint.startsWith("https:")?{protocol:"https:",rejectUnauthorized:!H.insecure}:void 0}),L=H.ttl,t=N$(L?()=>g$($,L):$,H.numTransports??16);return u$(a$,t)}export{T$ as xk,x$ as yk,a$ as zk,ML as Ak};
                                               ^

Error: Failed to load native binding for linux/x64 (expected: ./merkle-tree-napi.linux-x64-gnu.node)
Original error: Error: /lib64/libm.so.6: version `GLIBC_2.29' not found (required by /root/.local/share/cursor-agent/versions/2025.09.12-4852336/a3h1d327.node)
    at Object..node (node:internal/modules/cjs/loader:1846:18)
    at Module.load (node:internal/modules/cjs/loader:1423:32)
    at Function._load (node:internal/modules/cjs/loader:1246:12)
    at TracingChannel.traceSync (node:diagnostics_channel:322:14)
    at wrapModuleLoad (node:internal/modules/cjs/loader:235:24)
    at Module.require (node:internal/modules/cjs/loader:1445:12)
    at require (node:internal/modules/helpers:135:16)
    at file:///root/.local/share/cursor-agent/versions/2025.09.12-4852336/index-tqajwqmd.js:1:726
    at file:///root/.local/share/cursor-agent/versions/2025.09.12-4852336/index-0xg83y2p.js:1:377
    at file:///root/.local/share/cursor-agent/versions/2025.09.12-4852336/index-tqajwqmd.js:1:1149
    at file:///root/.local/share/cursor-agent/versions/2025.09.12-4852336/index-tqajwqmd.js:2:48
    at file:///root/.local/share/cursor-agent/versions/2025.09.12-4852336/index-0xg83y2p.js:1:377
    at file:///root/.local/share/cursor-agent/versions/2025.09.12-4852336/index-tqajwqmd.js:2:1539
    at ModuleJob.run (node:internal/modules/esm/module_job:343:25)
    at async onImport.tracePromise.__proto__ (node:internal/modules/esm/loader:647:26)
    at async asyncRunEntryPointWithESMLoader (node:internal/modules/run_main:117:5)

Node.js v22.18.0

Thank you all for the detailed reporting. The Issue has been sent to the team.

ntnunk seems this is still not fixed. to work with glibc 2.28 one would need version 2025.08.09, cursor seems not to maintain any download archive for older cursor cli versions, how do one find the tar for version 2025.08.09? how did you find version 2025.08.09? will be helpful if you could provide full download link

Do you know when this problem will be fixed? After 1 month, this problem sent to the team. And several days passed again, no patches released.

2 Likes

I do not have a specific timeline though the team has addressed several CLI issues and released updates. Might need a bit more time.

1 Like

does anyone know how to downgrade to this older version?

If you had the older version originally, it should still be present. I just have a alias that points at the specific version I want. For me the previous versions are in ~/.local/share/cursor/versions. I have no idea whether or not it’s possible to install a previous version, but I’d guess it probably is not.

Tried latest today and still doesn’t work :pensive_face: . Commenting to keep this alive.

Workarounds:

  • use a container → not ideal if you want the agent to run certain tools or start it’s own container based unit tests
  • get older version → can’t find it anywhere

same here

thanks for the response anyways :frowning: