codex cli crashes on rate_limit_exceeded

Resolved 💬 3 comments Opened Jun 26, 2025 by systematicguy Closed Aug 7, 2025

What version of Codex is running?

0.1.2505172129

Which model were you using?

gpt-4.1

What platform is your computer?

wsl

What steps can reproduce the bug?

give it a moderately big task with approx 1640 lines of existing code spread over 15 files to work with.

What is the expected behavior?

don't crash, do some exponential backoff

What do you see instead?

file:///home/david/.nvm/versions/node/v22.14.0/lib/node_modules/@openai/codex/dist/cli.js:582
`,"\r"]);Gh.NEWLINE_REGEXP=/\r\n|[\n\r]/g;function bVe(e,t){for(let a=t??0;a<e.length;a++){if(e[a]===10)return{preceding:a,index:a+1,carriage:!1};if(e[a]===13)return{preceding:a,index:a+1,carriage:!0}}return null}function qde(e){for(let n=0;n<e.length-1;n++){if(e[n]===10&&e[n+1]===10||e[n]===13&&e[n+1]===13)return n+2;if(e[n]===13&&e[n+1]===10&&n+3<e.length&&e[n+2]===13&&e[n+3]===10)return n+4}return-1}f();function zL(e){if(e[Symbol.asyncIterator])return e;let t=e.getReader();return{async next(){try{let r=await t.read();return r?.done&&t.releaseLock(),r}catch(r){throw t.releaseLock(),r}},async return(){let r=t.cancel();return t.releaseLock(),await r,{done:!0,value:void 0}},[Symbol.asyncIterator](){return this}}}var ed=class e{constructor(t,r){this.iterator=t,this.controller=r}static fromSSEResponse(t,r){let n=!1;async function*a(){if(n)throw new Error("Cannot iterate over a consumed stream, use `.tee()` to split the stream.");n=!0;let i=!1;try{for await(let o of SVe(t,r))if(!i){if(o.data.startsWith("[DONE]")){i=!0;continue}if(o.event===null||o.event.startsWith("response.")||o.event.startsWith("transcript.")){let s;try{s=JSON.parse(o.data)}catch(u){throw console.error("Could not parse message into JSON:",o.data),console.error("From chunk:",o.raw),u}if(s&&s.error)throw new xi(void 0,s.error,void 0,qL(t.headers));yield s}else{let s;try{s=JSON.parse(o.data)}catch(u){throw console.error("Could not parse message into JSON:",o.data),console.error("From chunk:",o.raw),u}if(o.event=="error")throw new xi(void 0,s.error,s.message,void 0);yield{event:o.event,data:s}}}i=!0}catch(o){if(o instanceof Error&&o.name==="AbortError")return;throw o}finally{i||r.abort()}}return new e(a,r)}static fromReadableStream(t,r){let n=!1;async function*a(){let o=new Gh,s=zL(t);for await(let u of s)for(let p of o.decode(u))yield p;for(let u of o.flush())yield u}async function*i(){if(n)throw new Error("Cannot iterate over a consumed stream, use `.tee()` to split the stream.");n=!0;let o=!1;try{for await(let s of a())o||s&&(yield JSON.parse(s));o=!0}catch(s){if(s instanceof Error&&s.name==="AbortError")return;throw s}finally{o||r.abort()}}return new e(i,r)}[Symbol.asyncIterator](){return this.iterator()}tee(){let t=[],r=[],n=this.iterator(),a=i=>({next:()=>{if(i.length===0){let o=n.next();t.push(o),r.push(o)}return i.shift()}});return[new e(()=>a(t),this.controller),new e(()=>a(r),this.controller)]}toReadableStream(){let t=this,r,n=new TextEncoder;return new RB({async start(){r=t[Symbol.asyncIterator]()},async pull(a){try{let{value:i,done:o}=await r.next();if(o)return a.close();let s=n.encode(JSON.stringify(i)+`
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        

e [Error]: Rate limit reached for gpt-4.1 in organization org-7OUlVMWja9b9bJPrdkhM4Toc on tokens per min (TPM): Limit 30000, Used 20356, Requested 12901. Please try again in 6.514s. Visit https://platform.openai.com/account/rate-limits to learn more.
    at e.a [as iterator] (file:///home/david/.nvm/versions/node/v22.14.0/lib/node_modules/@openai/codex/dist/cli.js:582:1514)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
    at async ky.run (file:///home/david/.nvm/versions/node/v22.14.0/lib/node_modules/@openai/codex/dist/cli.js:599:2785) {
  status: undefined,
  headers: undefined,
  request_id: undefined,
  error: {
    type: 'tokens',
    code: 'rate_limit_exceeded',
    message: 'Rate limit reached for gpt-4.1 in organization org-7OUlVMWja9b9bJPrdkhM4Toc on tokens per min (TPM): Limit 30000, Used 20356, Requested 12901. Please try again in 6.514s. Visit https://platform.openai.com/account/rate-limits to learn more.',
    param: null
  },
  code: 'rate_limit_exceeded',
  param: null,
  type: 'tokens'
}

Node.js v22.14.0

Additional information

_No response_

View original on GitHub ↗

3 Comments

tymrtn · 1 year ago

Happened to me too. It should handle this gracefully.

codex-maintainers · 1 year ago

Thank you for the feedback! Please try running the latest version of Codex CLI, as we've been addressing issues like this in our ongoing development. If the problem persists, feel free to open a new issue or contribute to the codex-rs/ implementation. You can find more details in our project update.

ClassyCircuit · 10 months ago

@codex-maintainers it is not fixed with the latest release. API keys are being aggressively rate limited and streams are disconnected. Please add a config option to set the current rate limit, so Codex would take that into account when sending multiple requests and spread them out evenly.