forge-debugger
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseForge App Debugger
Forge应用调试器
Diagnose and fix issues in Atlassian Forge apps. Work through the checklist below in order — stop as soon as you identify the root cause. Every step after the root cause wastes tokens and context.
诊断并修复Atlassian Forge应用中的问题。按顺序完成以下检查清单——一旦确定根本原因就停止操作。在找到根本原因后继续执行后续步骤会浪费令牌和上下文。
EXECUTION MANDATE
执行要求
You are authorized to run all diagnostic and fix commands without asking permission. When you identify a fix, run it immediately. Do NOT:
- Say "you should run..." or "here's what I would do..." or "run this command in your terminal"
- Ask "shall I proceed?" before executing a fix you already have all the inputs for
- Present commands as copy-paste instructions when you could run them yourself
Wrong: "Here's what I would do to fix this: run ..."
Right: (runs immediately and reports the result)
forge lintforge lintThe only exceptions: commands requiring an interactive terminal (, ) must be run by the user in their own terminal — tell them exactly what to run and why.
forge loginforge tunnel您有权运行所有诊断和修复命令,无需请求许可。当确定修复方案后,立即执行。请勿:
- 说“您应该运行...”或“我会这样做...”或“在终端中运行此命令”
- 在执行已有全部输入信息的修复操作前询问“是否继续?”
- 当您可以自行运行命令时,将命令作为复制粘贴指令呈现
错误示例: "我会这样修复:运行 ..."
正确示例: (立即运行 并报告结果)
forge lintforge lint唯一例外:需要交互式终端的命令(、)必须由用户在自己的终端中运行——明确告知他们要运行的命令及原因。
forge loginforge tunnelDiagnostic Principles
诊断原则
- Cheap first: lint and version checks cost nothing. Run them before reading source code or logs.
- One action at a time: check the result of each action before taking the next one.
- Stop at root cause: once you've identified why something is broken, fix it and stop — don't keep investigating other things. Exception: if the app has multiple independent bugs (e.g. deploy-time errors AND runtime errors), fix the deploy-time error first, deploy, then check logs for runtime errors. Don't declare "fixed" after only resolving the first layer.
- Own the fixes: run the fix commands yourself, don't hand them to the user.
- Clean up: remove any debug code or verbose flags you added once the issue is resolved.
- npx fallback: if CLI can't be installed globally (permission errors, no sudo), use
forgeas a drop-in replacement for all forge commands.npx @forge/cli
- 先做低成本检查:lint检查和版本检查无需成本。在读取源代码或日志前先运行这些检查。
- 一次执行一个操作:在执行下一个操作前检查当前操作的结果。
- 找到根本原因即停止:一旦确定问题原因,修复后就停止——不要继续调查其他内容。例外情况:如果应用存在多个独立的bug(例如部署时错误和运行时错误),先修复部署时错误,完成部署后再检查运行时错误日志。不要仅解决第一层问题就宣称“已修复”。
- 负责修复操作:自行运行修复命令,不要让用户执行。
- 清理环境:问题解决后,移除添加的所有调试代码或冗余标志。
- npx备选方案:如果无法全局安装CLI(权限错误、无sudo权限),使用
forge作为所有forge命令的替代方案。npx @forge/cli
Step 1: Classify the Error
步骤1:错误分类
Before running any commands, ask one question if the user hasn't made it clear:
"Is this a deploy-time error (forge deploy fails), a runtime error (app crashes or shows wrong data after deploying), or a visibility issue (app deployed but not appearing)?"
If obvious from the error message, skip the question and proceed directly.
Quick routing:
| Symptom | Go to |
|---|---|
| Step 2 → 3 → 4 |
| App not visible after install | Step 3 → common error: "App not installed" |
| App crashes / resolver error | Step 3 → 5 → 6 |
| Blank UI / Custom UI not rendering | Step 3 → 4 → common error: "blank Custom UI" |
| Works in dev, fails in prod | Step 7 (Production) |
| Permission denied / 403 | Common error: "Permission denied" |
| 410 Gone / deprecated endpoint | Common error: "410 Gone" → API Migration section |
| Handler path lint error | Common error: "cannot find associated file" → Handler Path Resolution section |
| Resolver returns undefined, no errors | Common error: invoke name mismatch → Invoke Name vs Function Key section |
| Multiple failures (deploy + runtime) | Fix deploy errors first, deploy, then check logs for runtime errors |
在运行任何命令前,如果用户未明确说明,先询问一个问题:
"这是部署时错误(forge deploy失败)、运行时错误(应用部署后崩溃或显示错误数据),还是可见性问题(应用已部署但未显示)?"
如果错误信息已明确表明类型,跳过此问题直接继续。
快速路由:
| 症状 | 跳转至 |
|---|---|
| 步骤2 → 3 → 4 |
| 安装后应用不可见 | 步骤3 → 常见错误:“应用未安装” |
| 应用崩溃 / resolver错误 | 步骤3 → 5 → 6 |
| 空白UI / Custom UI无法渲染 | 步骤3 → 4 → 常见错误:“空白Custom UI” |
| 开发环境正常,生产环境失败 | 步骤7(生产环境) |
| 权限被拒绝 / 403 | 常见错误:“权限被拒绝” |
| 410 Gone / 已弃用端点 | 常见错误:“410 Gone” → API迁移部分 |
| 处理程序路径lint错误 | 常见错误:“无法找到关联文件” → 处理程序路径解析部分 |
| Resolver返回undefined,无错误 | 常见错误:调用名称不匹配 → 调用名称与函数键部分 |
| 多个故障(部署+运行时) | 先修复部署错误,完成部署后再检查运行时错误日志 |
Step 2: Version Check
步骤2:版本检查
bash
forge --version
npm show @forge/cli versionIf the installed version is behind the latest major version, upgrade immediately:
bash
npm install -g @forge/cliThen retry the failing operation. Many bugs are fixed in newer CLI versions.
bash
forge --version
npm show @forge/cli version如果已安装版本落后于最新主版本,立即升级:
bash
npm install -g @forge/cli然后重试失败的操作。许多bug在新版本CLI中已被修复。
Step 3: Lint
步骤3:Lint检查
bash
forge lintFix every error before proceeding — lint errors cause deploy failures and silent runtime bugs. If lint passes cleanly, continue to the next step.
For any manifest-related error message (e.g. "invalid manifest", "unexpected key", "modules.jira:*" errors): run first before reading any source files. Lint will identify the exact line and field causing the problem — reading the file before linting is wasteful and usually less informative than the lint output.
forge lintbash
forge lint在继续操作前修复所有错误——lint错误会导致部署失败和静默运行时bug。如果lint检查完全通过,继续下一步。
对于任何清单相关错误信息(例如“无效清单”、“意外键”、“modules.jira:*”错误):在读取任何源文件前先运行。Lint检查会指出问题的确切行和字段——在lint前读取文件既浪费时间,通常也不如lint输出信息丰富。
forge lintStep 4: Custom UI Build Check
步骤4:Custom UI构建检查
Only applies when the app has a directory (Custom UI apps). Check if the frontend was built before the last deploy:
static/bash
ls -la static/build/If the build directory is missing or older than recent source changes, rebuild:
bash
cd static && npm run build && cd ..Then redeploy:
bash
forge deploy -e developmentThis is one of the most common causes of blank UI panels.
仅适用于包含目录的应用(Custom UI应用)。检查上次部署前是否已构建前端:
static/bash
ls -la static/build/如果构建目录缺失或早于最近的源代码更改,重新构建:
bash
cd static && npm run build && cd ..然后重新部署:
bash
forge deploy -e development这是空白UI面板最常见的原因之一。
Step 5: Deploy Status
步骤5:部署状态
Verify the app was actually deployed successfully:
bash
forge deploy -e development --verboseWatch for errors in the output. Note the deploy timestamp. If deploy fails, the error message usually identifies the problem directly — match it against the Common Error Patterns table below.
验证应用是否已成功部署:
bash
forge deploy -e development --verbose观察输出中的错误。记录部署时间戳。如果部署失败,错误信息通常会直接指出问题——将其与下方的常见错误模式表匹配。
Step 6: Logs
步骤6:日志
bash
forge logs -e development --limit 100Read the logs carefully. Most runtime errors appear here.
bash
forge logs -e development --limit 100仔细阅读日志。大多数运行时错误会出现在此处。
If no logs are returned
如果未返回日志
The resolver may not have been triggered, or logging isn't set up. Add a debug log at the entry point of the resolver:
javascript
// Add at the top of your handler function:
console.error('[DEBUG] Handler called with:', JSON.stringify(payload));Then redeploy and trigger the app again:
bash
forge deploy -e development
forge logs -e development --limit 100Remove the debug log after you've identified the issue.
Resolver可能未被触发,或未设置日志。在Resolver的入口点添加调试日志:
javascript
// 添加到处理函数顶部:
console.error('[DEBUG] Handler called with:', JSON.stringify(payload));然后重新部署并再次触发应用:
bash
forge deploy -e development
forge logs -e development --limit 100确定问题后移除调试日志。
If the error is in the frontend (UI rendering, blank screen)
如果错误出现在前端(UI渲染、空白屏幕)
Forge UI Kit errors surface in , not the browser console. For Custom UI, add error logging in the resolver that backs the UI:
forge logsjavascript
try {
const result = await api.asUser().requestJira(/* ... */);
return result;
} catch (err) {
console.error('[DEBUG] Resolver error:', err.message, err.stack);
throw err;
}Redeploy, trigger, and check logs.
Forge UI Kit错误会显示在中,而非浏览器控制台。对于Custom UI,在支持UI的Resolver中添加错误日志:
forge logsjavascript
try {
const result = await api.asUser().requestJira(/* ... */);
return result;
} catch (err) {
console.error('[DEBUG] Resolver error:', err.message, err.stack);
throw err;
}重新部署、触发应用并检查日志。
Step 7: Production Issues
步骤7:生产环境问题
If the user reports an issue that only happens in production (or on a specific customer's site):
- Ask: "Which Atlassian site is affected? (e.g. )"
customername.atlassian.net - Check production logs:
bash
forge logs -e production --site <customer-site> --limit 100 - Note: production logs may be delayed up to 2 minutes after the event.
- If the issue is permission-related, check whether scopes were upgraded after a new install — production installs require explicit .
--upgrade
如果用户报告仅在生产环境(或特定客户站点)出现的问题:
- 询问:“受影响的Atlassian站点是哪个?(例如 )”
customername.atlassian.net - 检查生产环境日志:
bash
forge logs -e production --site <customer-site> --limit 100 - 注意:生产环境日志可能在事件发生后延迟最多2分钟才会显示。
- 如果问题与权限相关,检查新安装后是否已升级scopes——生产环境安装需要显式使用参数。
--upgrade
Common Error Patterns
常见错误模式
Match the error against this table first. If you find a match, apply the fix directly without further investigation.
| Error / Symptom | Root Cause | Fix |
|---|---|---|
| "App is not installed on this site" | | Ask for the Atlassian site URL if not already known, then run it yourself: |
| Blank panel / Custom UI white screen | Frontend build not run before deploy | |
| "Resolver not found" or resolver returns undefined | Function key in manifest.yml doesn't match resolver registration | Check |
| 403 / "Permission denied" / "Unauthorized" | OAuth scope missing from manifest | Add scope to |
| YAML syntax error in manifest.yml | Run |
| App deployed but module not visible | Wrong product in | Verify |
| "forge: command not found" | CLI not installed | |
| | |
| "Rate limit exceeded" | Too many API calls in resolver | Add exponential backoff; check for resolver being called in a loop |
| "App tunnel disconnected" | | Re-run |
| "Cannot read properties of undefined" | API response shape unexpected | Log the full API response; add null checks |
| 410 Gone / "deprecated endpoint has been removed" | Confluence/Jira REST API endpoint removed | Migrate to v2 API (see API Migration section below). Redeploy and check logs |
| Handler path in manifest.yml doesn't match actual file location | Handler path is relative to |
| Frontend | The invoke name must exactly match the resolver.define name. Check both files — this is a different check than function key in manifest |
| Handler path includes | Remove |
| No sudo or write access to global npm directory | Use |
先将错误与此表匹配。如果找到匹配项,直接应用修复方案,无需进一步调查。
| 错误/症状 | 根本原因 | 修复方案 |
|---|---|---|
| "此站点未安装应用" | 未运行 | 如果尚未知晓,询问Atlassian站点URL,然后自行运行: |
| 空白面板 / Custom UI白屏 | 部署前未运行前端构建 | |
| "Resolver未找到"或resolver返回undefined | manifest.yml中的函数键与resolver注册不匹配 | 检查 |
| 403 / "权限被拒绝" / "未授权" | manifest中缺失OAuth scope | 向 |
| manifest.yml存在YAML语法错误 | 运行 |
| 应用已部署但模块不可见 | | 验证 |
| "forge: command not found" | 未安装CLI | |
部署时出现 | 未在应用目录中运行 | |
| "Rate limit exceeded" | Resolver中API调用过多 | 添加指数退避机制;检查Resolver是否被循环调用 |
| "App tunnel disconnected" | | 重新运行 |
| "Cannot read properties of undefined" | API响应结构不符合预期 | 记录完整API响应;添加空值检查 |
| 410 Gone / "已弃用端点已被移除" | Confluence/Jira REST API端点已被移除 | 迁移到v2 API(参见下方API迁移部分)。重新部署并检查日志 |
| manifest.yml中的处理程序路径与实际文件位置不匹配 | 处理程序路径是相对于 |
| 前端 | 调用名称必须与resolver.define名称完全一致。检查两个文件——这与manifest中的函数键检查是独立的 |
部署时出现 | 处理程序路径包含 | 移除处理程序路径中的 |
| 无sudo权限或对全局npm目录无写入权限 | 使用 |
Handler Path Resolution
处理程序路径解析
The field in has the format , where:
handlermanifest.yml<path>.<export>- is the file path relative to
<path>(withoutsrc/prefix, without file extension)src/ - is the named export from that file
<export>
Examples:
| Resolver file location | Export in file | Correct handler value |
|---|---|---|
| | |
| | |
| | |
Common mistakes:
- — wrong if the file is in a subdirectory like
index.handlersrc/resolvers/ - — wrong: bundler prefixes
src/resolvers/index.handlerautomatically, resulting insrc/src/src/resolvers/... - — wrong if the file exports
resolvers/index.runnothandlerrun
Diagnostic trick: If reports "cannot find associated file" but you're sure the file exists, try . The bundler error message shows the fully resolved path, which reveals whether the path is being doubled or misresolved.
forge lintforge deploy --no-verifymanifest.ymlhandler<path>.<export>- 是**相对于
<path>**的文件路径(不带src/前缀,不带文件扩展名)src/ - 是该文件中的命名导出
<export>
示例:
| Resolver文件位置 | 文件中的导出 | 正确的handler值 |
|---|---|---|
| | |
| | |
| | |
常见错误:
- — 如果文件位于
index.handler之类的子目录中,此值错误src/resolvers/ - — 错误:打包器会自动添加
src/resolvers/index.handler前缀,导致路径变为src/src/src/resolvers/... - — 如果文件导出的是
resolvers/index.run而非handler,此值错误run
诊断技巧: 如果报告“无法找到关联文件”但您确定文件存在,尝试运行。打包器的错误消息会显示完整解析路径,从而揭示路径是否重复或解析错误。之后务必修复根本原因——不要使用进行部署。
forge lintforge deploy --no-verify--no-verifyInvoke Name vs Function Key
调用名称与函数键
There are two separate name-matching requirements for UI Kit resolvers:
- manifest.yml must match the
function.keyreference in the module definitionresolver: function: - Frontend must exactly match
invoke('name')in the backendresolver.define('name', ...)
These are independent — you can have the manifest function key correct but still get undefined results if the invoke name doesn't match resolver.define. When debugging "resolver returns undefined" with no errors in logs, always check both matching relationships.
UI Kit resolver有两个独立的名称匹配要求:
- **manifest.yml中的**必须与模块定义中的
function.key引用匹配resolver: function: - **前端必须与后端
invoke('name')**完全匹配resolver.define('name', ...)
这些是独立的——即使manifest中的函数键正确,如果调用名称与resolver.define不匹配,仍会返回undefined结果。当调试“resolver返回undefined且日志无错误”时,务必检查两种匹配关系。
API Migration (v1 → v2)
API迁移(v1 → v2)
Atlassian is progressively deprecating v1 REST API endpoints. When you see a 410 Gone response:
- Check for the exact error — it will show which endpoint returned 410
forge logs - Identify the v2 equivalent:
- URL pattern: →
/wiki/rest/api/content/...(or/wiki/api/v2/pages/...,/blogposts/...)/spaces/... - Jira: →
/rest/api/2/.../rest/api/3/...
- URL pattern:
- Update pagination: v2 Confluence APIs use cursor-based pagination (parameter) instead of offset-based (
cursorparameter). The next cursor is instartdata._links.next - Update response shape: v2 may return different field names (e.g. instead of nested
authorId)by.accountId - Redeploy and check logs to confirm the fix
Do NOT treat 410 as a permissions issue — it means the endpoint no longer exists, not that access is denied.
Atlassian正逐步弃用v1 REST API端点。当看到410 Gone响应时:
- 检查获取确切错误——会显示哪个端点返回410
forge logs - 确定v2等效端点:
- URL模式:→
/wiki/rest/api/content/...(或/wiki/api/v2/pages/...、/blogposts/...)/spaces/... - Jira:→
/rest/api/2/.../rest/api/3/...
- URL模式:
- 更新分页:v2 Confluence API使用基于游标的分页(参数)而非基于偏移量的分页(
cursor参数)。下一个游标位于start中data._links.next - 更新响应结构:v2可能返回不同的字段名称(例如而非嵌套的
authorId)by.accountId - 重新部署并检查日志确认修复
请勿将410错误视为权限问题——这表示端点已不存在,而非访问被拒绝。
Step 8: Cleanup
步骤8:清理
Once the issue is resolved:
- Remove any statements you added.
console.error('[DEBUG] ...') - Remove verbose flags from any scripts.
- Run one final time to confirm clean state.
forge lint - Redeploy if you modified code during debugging:
bash
forge deploy -e development - Confirm the fix works by triggering the app and checking that shows no new errors.
forge logs
问题解决后:
- 移除添加的所有语句。
console.error('[DEBUG] ...') - 移除脚本中的冗余标志。
- 最后运行一次确认状态正常。
forge lint - 如果调试期间修改了代码,重新部署:
bash
forge deploy -e development - 触发应用并检查无新错误,确认修复有效。
forge logs
Escalation
升级处理
If none of the above resolves the issue:
- Run for extended output.
forge logs -e development --verbose --limit 200 - Check the Forge changelog for known issues:
search-forge-docs "known issues <error-text>" - If the error is in a Forge platform API (not your code), note the from the log output — this is what Atlassian support needs.
traceId
如果以上步骤均无法解决问题:
- 运行获取扩展输出。
forge logs -e development --verbose --limit 200 - 检查Forge变更日志中的已知问题:
search-forge-docs "known issues <error-text>" - 如果错误出现在Forge平台API中(非您的代码),记录日志输出中的——这是Atlassian支持所需的信息。
traceId
Authentication Errors
认证错误
If any command fails with "not authenticated" or "run forge login":
- Tell the user to create an API token at https://id.atlassian.com/manage/api-tokens
- Tell them to run in their own terminal (not via the agent) — it will prompt for their email and the API token
forge login - Example message: "You need to log in. Create an API token at https://id.atlassian.com/manage/api-tokens, then run in your terminal. Enter your Atlassian email and the token when prompted — do not paste the token here."
forge login - After they confirm login, resume debugging from where you left off.
如果任何命令失败并显示“未认证”或“运行forge login”:
- 告知用户在**https://id.atlassian.com/manage/api-tokens**创建API令牌
- 告知他们在自己的终端中运行(而非通过代理)——会提示输入邮箱和API令牌
forge login - 示例消息:“您需要登录。请在https://id.atlassian.com/manage/api-tokens创建API令牌,然后在终端中运行`forge login`。提示时输入您的Atlassian邮箱和令牌——请勿在此处粘贴令牌。”
- 用户确认登录后,从之前中断的位置恢复调试。
Token Efficiency Rules
令牌效率规则
Follow these to keep context usage low:
- Read before reading any source file — logs usually reveal the root cause without needing to inspect code.
forge logs - Read only the specific file implicated by the error. Match the error to its file:
- → check only
npm ERR! missing script: build(scripts section)package.json - /
invalid manifest→ rununexpected keyfirst, then only the specific manifest fieldforge lint - → check only the function key in
Resolver not foundvsmanifest.ymlin the resolver fileresolver.define() - → check only the scopes in
403 / permission deniedmanifest.yml - → check the API endpoint URL in the resolver file; don't check scopes or manifest
410 Gone - → check the handler path in
cannot find associated fileand the file location; usemanifest.ymlto see the bundler's resolved path--no-verify - returns undefined → check both the frontend
invoke()AND backendinvoke('name')— two files, but targeted readsresolver.define('name')
- Don't read for npm/build errors — they are unrelated.
manifest.yml - Don't re-read a file you've already read in this session unless it changed.
- Stop the diagnostic chain the moment you find a match in the Common Error Patterns table. Exception: when multiple independent bugs exist (e.g. deploy error + runtime error), fix the first, deploy, then check for the next.
- Don't run more than once per fix attempt without a clear reason.
forge deploy - Use as a diagnostic step when lint blocks deploy but you suspect the lint error may be misleading. The bundler error message often reveals the true path resolution issue. Always fix the root cause afterward — don't ship with
forge deploy --no-verify.--no-verify
遵循以下规则以降低上下文使用量:
- 在读取任何源文件前先读取——日志通常无需检查代码即可揭示根本原因。
forge logs - 仅读取错误关联的特定文件。将错误与对应文件匹配:
- → 仅检查
npm ERR! missing script: build(scripts部分)package.json - /
invalid manifest→ 先运行unexpected key,然后仅检查特定的manifest字段forge lint - → 仅检查
Resolver not found中的函数键与resolver文件中的manifest.ymlresolver.define() - → 仅检查
403 / permission denied中的scopesmanifest.yml - → 检查resolver文件中的API端点URL;不要检查scopes或manifest
410 Gone - → 检查
cannot find associated file中的处理程序路径和文件位置;使用manifest.yml查看打包器的解析路径--no-verify - 返回undefined → 检查前端
invoke()和后端invoke('name')——两个文件,但仅读取相关部分resolver.define('name')
- 不要为npm/build错误读取——两者无关。
manifest.yml - 除非文件已更改,否则不要重新读取本次会话中已读取过的文件。
- 在常见错误模式表中找到匹配项后立即停止诊断流程。例外情况:当存在多个独立bug时(例如部署错误+运行时错误),先修复第一个,部署后再检查下一个。
- 无明确理由时,每次修复尝试不要运行超过一次。
forge deploy - 当lint阻止部署但您怀疑lint错误可能有误导性时,使用作为诊断步骤。打包器的错误消息通常会揭示真实的路径解析问题。之后务必修复根本原因——不要使用
forge deploy --no-verify进行部署。--no-verify