The "Show more" button in the Codex Desktop App repeatedly toggles for long messages, causing the conversation scrollbar to continuously jump.
What version of the Codex App are you using (From “About Codex” dialog)?
ChatGPT Powered by Codex & OWL 版本 26.707.31428 发布于 2026年7月10日(Due to the merger of Codex and ChatGPT today, only the ChatGPT version can be viewed.)
What subscription do you have?
gpt plus
What platform is your computer?
Microsoft Windows NT 10.0.26200.0 x64
What issue are you seeing?
Phenomenon:
- The problem is triggered by a user input message. This user input is automatically displayed by Codex as "Expand More", and it repeatedly expands and collapses when scrolling near this message, causing the scroll bar of the entire task conversation to continuously jump.
- Switching to other tasks and then returning to this one, it is temporarily normal before rolling to the vicinity of this message.
- Once scrolling to the vicinity of this extremely long reply, the jumping immediately begins.
- Restarting Codex after this problem still exists because reloading the same task history will trigger it again.
- This is not caused by the project web page or code, but a rendering issue of the conversation UI in the Codex Desktop App.
Reproduction steps:
- Open a project in the Codex Desktop App that already contains a long historical conversation, then input a conversation that may contain a special format / long Markdown / long code block.
- Scroll near the input of this conversation.
- The conversation (user input) shows an "Expand More" button, and "Expand More" repeatedly expands and collapses.
- Each height change triggers the recalculation of the scroll anchor, causing the scroll bar to continuously jump, making the entire conversation page unstable and constantly jumping.
Attempts:
- Returning to the problem after switching tasks still exists
- Completely closing and reopening Codex still exists
- Attempting to open a new conversation input and copy the original conversation content, unable to reproduce, and no "Expand More" option appeared
- In the current conversation with the bug, attempts were also made to input data with bugs, but the issue could not be reproduced either.
- Let Codex output first. Before the input with the bug occurs, the content it replies with will be used. Then, when the user inputs the input with the bug, it cannot be reproduced.
Guess:
This conversation was previously discussing writing a prompt with Codex. The replies before and after this conversation all contain long Markdown, and multiple "-" characters caused this user input to have the "Expand More" button and be incorrectly repeatedly expanded and collapsed.
Additionally, I have reviewed the similar issues that were previously raised and none of them have been resolved but were directly closed. Please pay attention to this problem as it has occurred multiple times.
What steps can reproduce the bug?
Reproduction steps:
- Open a project in the Codex Desktop App that already contains a long historical conversation, then input a conversation that may contain a special format / long Markdown / long code block.
- Scroll near the input of this conversation.
- The conversation (user input) shows an "Expand More" button, and "Expand More" repeatedly expands and collapses.
- Each height change triggers the recalculation of the scroll anchor, causing the scroll bar to continuously jump, making the entire conversation page unstable and constantly jumping.
What is the expected behavior?
_No response_
Additional information
Before the user's input, the response content from Codex:
把下面整段直接发给其他同事的 AI 即可:
你正在给一个已有的 Agent 业务后端接入统一登录态。
先阅读当前项目结构、启动方式和依赖清单,再修改代码。不要执行 npm install、pip install 或其他安装命令;如需依赖,只修改依赖声明文件,并说明需要安装什么。
系统统一认证架构:
- 前端登录后,统一 Auth Server 将登录态写入 Redis。
- 浏览器只持有 HttpOnly Cookie:session_id。
- Redis 是唯一登录态来源。
- Redis 键格式:session:{session_id}
- Redis 值是 JSON,整体结构大致为:
{
"schemaVersion": 2,
"user": {
"userId": "用户唯一标识",
"userLoginName": "登录名",
"userName": "姓名",
"email": "邮箱",
"ip": "IP",
"domainId": "域ID",
"orgLevel3Name": "用户单位第三级名称",
"iat": 0,
"exp": 0,
"crossToken": null,
"authMode": "SSO"
},
"access": {
"isSuperAdmin": false,
"globalRoles": [
{
"roleId": "角色ID",
"roleName": "角色名称",
"roleCode": "角色编码"
}
],
"globalMenus": [
{
"menuId": "菜单ID",
"menuName": "菜单名称",
"permissionCode": "权限编码",
"routePath": "路由",
"parentId": null,
"visible": true,
"sortOrder": 0
}
]
}
}
目标:
为当前 Agent 后端的所有业务接口增加统一认证入口:
1. 从请求 Cookie 读取 session_id。
2. 使用 Redis 查询 session:{session_id}。
3. 若 Redis Session 存在且 JSON 合法:
- 获取 userInfo,即 session.user。
- 同时可获取 session.access 中的角色和菜单信息。
- 将用户上下文注入当前请求生命周期。
- 后续业务代码可直接获取当前用户,不再从请求参数、Header 或前端传 userId。
4. 若 Cookie 不存在、Session 不存在、Session 已过期、JSON 非法:
- 返回 HTTP 401 Unauthorized。
5. Redis 连接失败:
- 返回 HTTP 503 Service Unavailable。
- 不要把 Redis 故障伪装成 401。
6. 健康检查接口 `/health` 可不鉴权;其余业务 API 默认全部鉴权。
严格禁止:
- 不处理 sso_code。
- 不调用 SSO 服务。
- 不解析、验证或存储 sso_token/JWT。
- 不新增本地 token 体系。
- 不使用 localStorage token。
- 不自行创建、续期、删除 Redis Session。
- 不修改 session:{session_id} 的内容或 TTL。
- 不信任前端通过 Header、Body、Query 传来的 userId、角色或权限。
- 不把 Redis 密码、完整 session_id、用户敏感信息写入日志。
配置要求:
为当前服务新增环境变量,名称可沿用以下标准:
REDIS_URL=redis://:你的Redis密码@Redis宿主机IP:Redis映射端口/0
AUTH_SESSION_COOKIE_NAME=session_id
AUTH_SESSION_KEY_PREFIX=session:
说明:
- REDIS_URL 必须与统一 Auth Server 使用的是同一个 Redis 实例、同一个 DB 编号。
- 如果当前 Agent 后端运行在 Docker 容器中,不能把 127.0.0.1 当 Redis 地址。
- 当前部署若采用“宿主机 IP + Redis 映射端口”方式,就填写宿主机实际 IP。
- 若未来改成 Docker 私有网络,REDIS_URL 再改为 Redis 容器服务名即可,例如 redis://:密码@redis-container:6379/0。
- 不把真实密码写入代码、Dockerfile 或提交到仓库。
- 在项目现有的生产环境文件中配置,例如 agent_xxx.prod.env;不要强制使用 .env 文件名。
实现要求:
- 将认证实现为当前项目框架推荐的全局中间件、路由守卫、依赖注入或拦截器。
- FastAPI 推荐使用 Depends 或 router 级 dependencies。
- Node.js / TypeScript 推荐使用 Express / NestJS / Koa 对应的全局中间件或 Guard。
- 不要要求每个业务接口重复手写 Redis 查询。
- 请求上下文至少统一提供:
- userId
- userLoginName
- userName
- email
- domainId
- orgLevel3Name
- roles
- isSuperAdmin
- menus
- 业务接口通过“当前用户上下文”获取身份,例如 currentUser.userId。
请按以下顺序完成:
1. 先说明当前项目使用的后端框架、入口文件、配置文件和路由组织方式。
2. 新增认证模块,例如 auth_context / session_auth / middleware。
3. 修改环境变量示例文件和实际配置读取逻辑。
4. 把认证统一挂到业务 API 入口,不影响 `/health`。
5. 补充中文 README 或接入文档,写清楚环境变量、Docker 地址填写规则和用户上下文用法。
6. 增加最少的测试或可执行验证:
- 无 Cookie 返回 401。
- 不存在的 session_id 返回 401。
- Redis Session 存在时,接口可读到 user.userId。
- Redis 不可用时返回 503。
7. 最后列出修改的文件、接口行为和需要部署时配置的变量。
注意:当前任务只是“认证并注入用户上下文”。菜单/按钮级权限由后续网关或权限体系统一实现,当前 Agent 后端不要自行重新设计一套权限模型。
The user input with the bug:
首先把agent后端改为业务后端,其次,不要规定他的后续行为,也就是这些:
- 将用户上下文注入当前请求生命周期。,然后:
- 健康检查接口
/health可不鉴权;其余业务 API 默认全部鉴权。这个应该是说,做这个鉴权中间件,然后在入口层,除了健康检查其他api全部都走这个中间件,然后这一段什么玩意:
严格禁止:
- 不处理 sso_code。
- 不调用 SSO 服务。
- 不解析、验证或存储 sso_token/JWT。
- 不新增本地 token 体系。
- 不使用 localStorage token。
- 不自行创建、续期、删除 Redis Session。
- 不修改 session:{session_id} 的内容或 TTL。
- 不信任前端通过 Header、Body、Query 传来的 userId、角色或权限。
- 不把 Redis 密码、完整 session_id、用户敏感信息写入日志。,你知道双重否定表肯定吗,然后什么叫认证注入上下文,注意:当前任务只是“认证并注入用户上下文”。菜单/按钮级权限由后续网关或权限体系统一实现,当前 Agent 后端不要自行重新设计一套权限模型。,我们当前任务只是从redis里面拿信息,后续怎么用,我们不要规定,这是同事自己决定的,我们只需要帮助他们实现鉴权拿userinfo这个中间件
7 Comments
English translation:
What version of the Codex App are you using (From “About Codex” dialog)?
ChatGPT Powered by Codex & OWL version 26.707.31428, released on July 10, 2026 (Due to the merger of Codex and ChatGPT today, only the ChatGPT version can be viewed.)
What subscription do you have?
gpt plus
What platform is your computer?
Microsoft Windows NT 10.0.26200.0 x64
What issue are you seeing?
Phenomenon:
Reproduction steps:
Attempts:
Guess:
This conversation was previously discussing writing a prompt with Codex. The replies before and after this conversation all contain long Markdown, and multiple "-" characters caused this user input to have the "Expand More" button and be incorrectly repeatedly expanded and collapsed.
Additionally, I have reviewed the similar issues that were previously raised and none of them have been resolved but were directly closed. Please pay attention to this problem as it has occurred multiple times.
What steps can reproduce the bug?
Reproduction steps:
What is the expected behavior?
_No response_
Additional information
Before the user's input, the response content from Codex:
Send the entire section below directly to your colleague's AI:
The user input with the bug:
First, change “Agent backend” to “business backend.” Second, do not prescribe their subsequent behavior, meaning these parts:
/healthmay be exempt from authentication; all other business APIs must be authenticated by default. This should say to build this authentication middleware and then, at the entry layer, have all APIs except the health check go through this middleware. And what is this section supposed to mean:Strictly prohibited:
<!-- codex-issue-translator -->
Potential duplicates detected. Please review them and close your issue if it is a duplicate.
Powered by Codex Action
Additional observation:
The scrollbar loop appears to be caused by a long message's “Show more” control repeatedly expanding and collapsing while that message is near the viewport.
Each expand/collapse changes the rendered message height, then the conversation scroll position is recalculated, causing the scrollbar and viewport to jump continuously.
This can happen in an idle thread with no active generation. Switching away and back temporarily avoids the issue until scrolling reaches the affected message again.
Related reports:
#28718
#27168
#28755
#32016
#18109
Minimal message I've found to cause the issue
https://github.com/user-attachments/assets/81f41470-034e-4241-87bf-644c9f9b2855
I can also reproduce this on macOS 26.5.1 arm64 with Codex 26.707.30751.
Trigger: a long user message containing fenced code and lists in a narrow transcript (~529 pixel). Without input, it alternates between the clamped Show more state and full rendering about five times per second, causing large scroll jumps. The header and composer remain stable.
Codex logged
ResizeObserver loop completed with undelivered notificationserror. The errors drop while Review hides the transcript and resume when the thread returns.Renderer inspection suggests a feedback loop: the same Markdown node is observed/measured via
scrollHeightand conditionally given a 20-line-webkit-line-clamp. Clamping changes its geometry and retriggers the observer; scroll anchoring amplifies each height change.Suggested fix: measure an always-unclamped inner Markdown node and clip only an outer wrapper. A regression test at a narrow width should verify stable message height, stable
scrollTop, and zero observer-loop errors.Update: I used Codex to debug Codex 😄
Good news: with substantial help from OpenAI Codex itself, I was able to independently reproduce this issue, identify the renderer feedback loop, and validate a small mitigation prototype.
So yes — I used Codex to debug (and prototype a fix for) a Codex bug :D
TL;DR
The root cause is a self-triggering layout feedback loop caused by measuring and modifying the same DOM node.
The cycle:
element.scrollHeightto decide whether it should be collapsible.max-heightand-webkit-line-clamp: 20to that same measured Markdown node.The transcript scroll anchoring / virtualization layer then amplifies this message-height oscillation into the large scrollbar jumps reported in this issue.
This matches the independent macOS analysis in #32030 and explains the alternating full / normal /
Show moreframes reported in #32016.---
Renderer-level evidence
I inspected the official packaged Electron application (
app.asar) and found the relevant implementation path.This was not native executable decompilation. An Electron ASAR is a resource archive containing already-built JavaScript/CSS bundles.
Tested package:
OpenAI.Codex 26.707.3748.026.707.31428, build505942.1.0Relevant bundled modules:
use-measured-text-collapse-*.jsuse-resize-observer-*.jsgenerated-image-preview-*.jsuser-formatted-text-*.jsThe important finding is that measurement and presentation are coupled.
---
Collapse measurement
The packaged
use-measured-text-collapsehook calculates:and decides the collapse state based on the measured height:
Effectively:
---
Same node receives the collapsed style
The renderer passes the measurement ref to the Markdown node and also applies the collapsed style to that same node:
This means the value used to decide whether collapsing is needed is directly changed by the collapse presentation itself.
The resulting feedback loop is:
---
ResizeObserver behavior
I also inspected the bundled
use-resize-observerimplementation.The observer forwards resize entries directly to registered callbacks:
There is no additional stabilization layer between the DOM size change and the measurement callback.
Therefore:
This explains why the loop can continue while the conversation is otherwise idle.
---
Isolated A/B validation
I reproduced the behavior using an isolated copy of the packaged application.
The test used:
UserFormattedTextuseMeasuredTextCollapseResizeObserverConfiguration:
529 px497 pxNo installed WindowsApps package was modified, no credentials were copied, and no real signed-in session was used.
| Four-second run | ResizeObserver callbacks | Collapse-state records | Result |
| -------------------------------------------------------------- | -----------------------: | ---------------------: | ------------------------------------------- |
| Current
WebkitLineClamp: 20behavior | 558 | 557 | Continuous34 px ↔ 424/441 pxoscillation || Same behavior with only the
WebkitLineClampmutation removed | 4 | 2 startup states | Stable collapsed state |Control run:
Mitigation run:
and then remained stable.
The isolated harness validates the message-height feedback loop itself. It does not attempt to reproduce the complete signed-in transcript virtualization/scroll-anchor layer, which is already demonstrated by the recordings attached to this issue.
---
Suggested fix
The robust fix is to separate measurement from presentation.
Instead of measuring and clipping the same element:
ResizeObserverto the inner node;max-heightandoverflow: hiddenonly to the outer wrapper;line-clampfor arbitrary Markdown blocks.This keeps the measured height independent from the collapsed visual state.
As an emergency mitigation, removing only:
while keeping:
and the existing Show more/less control stopped the oscillation in the A/B test.
---
Why I am not opening a PR
I also searched the current public
openai/codexrepository.The Electron/webview React UI containing these components does not appear to be present there.
The public repository contains the CLI, Rust core/app-server/TUI, and SDK, but not the desktop renderer implementation involved here.
Therefore, a community PR against the public repository would not be meaningful for this specific fix.
The attached prototype is only a proof of concept against the packaged bundle. It is not intended as a production patch, installer, or replacement for the internal source implementation.
I am deliberately not attaching extracted OpenAI bundle code, the original ASAR, or a patched ASAR.
---
Investigation artifacts
I prepared a small investigation bundle containing only my own report and test material:
The archive contains:
Attachment:
codex-32030-investigation-artifacts.zip---
A friendly nudge to the OpenAI team 🙏
This issue reproduces on both Windows and macOS, can make affected conversations effectively unusable, and may continue consuming CPU/GPU resources while the thread is idle.
At this point we have:
Hopefully this investigation shortens the path to an internal fix.
Thank you to everyone who provided recordings, frame analysis, and additional platform reports. Those reports were genuinely useful in connecting the visible scrollbar jumping with the underlying message-height feedback loop.
---
AI-assistance disclosure
The investigation, bundle inspection tooling, experimental harness, mitigation prototype, and report were developed with substantial assistance from OpenAI Codex.
I directed the investigation, reviewed the relevant locations, and independently ran and verified the experiments locally.
In short:
codex-32030-investigation-artifacts.zip
Good news! The version released in the early morning has fixed this bug. Now I can close this issue.