[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-atlassian-forge-debugger":3,"mdc-i26358-key":37,"related-repo-atlassian-forge-debugger":3017,"related-org-atlassian-forge-debugger":3099},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":20,"repoUrl":21,"updatedAt":22,"license":23,"forks":24,"topics":25,"repo":32,"sourceUrl":35,"mdContent":36},"forge-debugger","diagnose and fix Atlassian Forge apps","Diagnoses and fixes issues in Atlassian Forge apps. Use this skill whenever a Forge app has errors, crashes, shows blank UI, fails to deploy, doesn't appear after installation, has permission issues, or produces unexpected output. Trigger on any mention of forge logs, forge deploy errors, resolver errors, blank panels, missing scopes, Custom UI not rendering, production vs dev discrepancies, or any Jira\u002FConfluence app that \"stopped working\". Also trigger when the user asks to debug, troubleshoot, investigate, or fix a Forge app issue — even if they haven't used the word \"Forge\" but describe a Jira panel or Confluence macro acting up.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},"atlassian","Atlassian","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fatlassian.png",[12,16,17],{"name":13,"slug":14,"type":15},"Deployment","deployment","tag",{"name":9,"slug":8,"type":15},{"name":18,"slug":19,"type":15},"Debugging","debugging",14,"https:\u002F\u002Fgithub.com\u002Fatlassian\u002Fforge-skills","2026-07-12T07:58:47.226713",null,7,[26,27,28,29,30,31],"agent-skills","ai-agents","claude-code-plugin","claude-code-skills","gemini-cli-extension","mcp",{"repoUrl":21,"stars":20,"forks":24,"topics":33,"description":34},[26,27,28,29,30,31],"The Forge Skills Plugin bundles several Forge-focused skills plus MCP-backed tooling so your agent can scaffold apps, review them before deploy, debug production issues, and stay current on Forge APIs and the Atlassian Design System.","https:\u002F\u002Fgithub.com\u002Fatlassian\u002Fforge-skills\u002Ftree\u002FHEAD\u002Fskills\u002Fforge-debugger","---\nname: forge-debugger\ndescription: Diagnoses and fixes issues in Atlassian Forge apps. Use this skill whenever a Forge app has errors, crashes, shows blank UI, fails to deploy, doesn't appear after installation, has permission issues, or produces unexpected output. Trigger on any mention of forge logs, forge deploy errors, resolver errors, blank panels, missing scopes, Custom UI not rendering, production vs dev discrepancies, or any Jira\u002FConfluence app that \"stopped working\". Also trigger when the user asks to debug, troubleshoot, investigate, or fix a Forge app issue — even if they haven't used the word \"Forge\" but describe a Jira panel or Confluence macro acting up.\n---\n\n# Forge App Debugger\n\nDiagnose 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.\n\n## EXECUTION MANDATE\n\nYou are authorized to run all diagnostic and fix commands without asking permission. When you identify a fix, **run it immediately**. Do NOT:\n- Say \"you should run...\" or \"here's what I would do...\" or \"run this command in your terminal\"\n- Ask \"shall I proceed?\" before executing a fix you already have all the inputs for\n- Present commands as copy-paste instructions when you could run them yourself\n\n**Wrong:** \"Here's what I would do to fix this: run `forge lint`...\"\n**Right:** *(runs `forge lint` immediately and reports the result)*\n\nThe only exceptions: commands requiring an interactive terminal (`forge login`, `forge tunnel`) must be run by the user in their own terminal — tell them exactly what to run and why.\n\n**Attribution:** prefix every `forge` command you run yourself with `ATL_FORGE_ATTRIBUTION_SKILL_NAME=forge-debugger` (e.g. `ATL_FORGE_ATTRIBUTION_SKILL_NAME=forge-debugger forge lint`; with the npx fallback, `ATL_FORGE_ATTRIBUTION_SKILL_NAME=forge-debugger npx @forge\u002Fcli lint`). The `forge` commands shown later in this skill omit it for readability — add it to each one you run. Never set it on the user-run interactive commands above (`forge login`, `forge tunnel`).\n\n## Diagnostic Principles\n\n- **Cheap first**: lint and version checks cost nothing. Run them before reading source code or logs.\n- **One action at a time**: check the result of each action before taking the next one.\n- **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.\n- **Own the fixes**: run the fix commands yourself, don't hand them to the user.\n- **Clean up**: remove any debug code or verbose flags you added once the issue is resolved.\n- **npx fallback**: if `forge` CLI can't be installed globally (permission errors, no sudo), use `npx @forge\u002Fcli` as a drop-in replacement for all forge commands.\n\n## Step 1: Classify the Error\n\nBefore running any commands, ask one question if the user hasn't made it clear:\n\n> \"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)?\"\n\nIf obvious from the error message, skip the question and proceed directly.\n\n**Quick routing:**\n\n| Symptom | Go to |\n|---------|-------|\n| `forge deploy` fails | Step 2 → 3 → 4 |\n| App not visible after install | Step 3 → common error: \"App not installed\" |\n| App crashes \u002F resolver error | Step 3 → 5 → 6 |\n| Blank UI \u002F Custom UI not rendering | Step 3 → 4 → common error: \"blank Custom UI\" |\n| Works in dev, fails in prod | Step 7 (Production) |\n| Permission denied \u002F 403 | Common error: \"Permission denied\" |\n| 410 Gone \u002F deprecated endpoint | Common error: \"410 Gone\" → API Migration section |\n| Handler path lint error | Common error: \"cannot find associated file\" → Handler Path Resolution section |\n| Resolver returns undefined, no errors | Common error: invoke name mismatch → Invoke Name vs Function Key section |\n| Multiple failures (deploy + runtime) | Fix deploy errors first, deploy, then check logs for runtime errors |\n\n## Step 2: Version Check\n\n```bash\nforge --version\nnpm show @forge\u002Fcli version\n```\n\nIf the installed version is behind the latest major version, upgrade immediately:\n\n```bash\nnpm install -g @forge\u002Fcli\n```\n\nThen retry the failing operation. Many bugs are fixed in newer CLI versions.\n\n## Step 3: Lint\n\n```bash\nforge lint\n```\n\nFix every error before proceeding — lint errors cause deploy failures and silent runtime bugs. If lint passes cleanly, continue to the next step.\n\n**For any manifest-related error message** (e.g. \"invalid manifest\", \"unexpected key\", \"modules.jira:*\" errors): run `forge lint` 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.\n\n## Step 4: Custom UI Build Check\n\nOnly applies when the app has a `static\u002F` directory (Custom UI apps). Check if the frontend was built before the last deploy:\n\n```bash\nls -la static\u002Fbuild\u002F\n```\n\nIf the build directory is missing or older than recent source changes, rebuild:\n\n```bash\ncd static && npm run build && cd ..\n```\n\nThen redeploy:\n\n```bash\nforge deploy -e development\n```\n\nThis is one of the most common causes of blank UI panels.\n\n## Step 5: Deploy Status\n\nVerify the app was actually deployed successfully:\n\n```bash\nforge deploy -e development --verbose\n```\n\nWatch 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.\n\n## Step 6: Logs\n\n```bash\nforge logs -e development --limit 100\n```\n\nRead the logs carefully. Most runtime errors appear here.\n\n### If no logs are returned\n\nThe resolver may not have been triggered, or logging isn't set up. Add a debug log at the entry point of the resolver:\n\n```javascript\n\u002F\u002F Add at the top of your handler function:\nconsole.error('[DEBUG] Handler called with:', JSON.stringify(payload));\n```\n\nThen redeploy and trigger the app again:\n\n```bash\nforge deploy -e development\nforge logs -e development --limit 100\n```\n\nRemove the debug log after you've identified the issue.\n\n### If the error is in the frontend (UI rendering, blank screen)\n\nForge UI Kit errors surface in `forge logs`, not the browser console. For Custom UI, add error logging in the resolver that backs the UI:\n\n```javascript\ntry {\n  const result = await api.asUser().requestJira(\u002F* ... *\u002F);\n  return result;\n} catch (err) {\n  console.error('[DEBUG] Resolver error:', err.message, err.stack);\n  throw err;\n}\n```\n\nRedeploy, trigger, and check logs.\n\n## Step 7: Production Issues\n\nIf the user reports an issue that only happens in production (or on a specific customer's site):\n\n1. Ask: \"Which Atlassian site is affected? (e.g. `customername.atlassian.net`)\"\n2. Check production logs:\n   ```bash\n   forge logs -e production --site \u003Ccustomer-site> --limit 100\n   ```\n3. Note: production logs may be delayed up to 2 minutes after the event.\n4. If the issue is permission-related, check whether scopes were upgraded after a new install — production installs require explicit `--upgrade`.\n\n## Common Error Patterns\n\nMatch the error against this table first. If you find a match, apply the fix directly without further investigation.\n\n| Error \u002F Symptom | Root Cause | Fix |\n|-----------------|-----------|-----|\n| \"App is not installed on this site\" | `forge install` wasn't run, or ran against wrong site | Ask for the Atlassian site URL if not already known, then run it yourself: `forge install --non-interactive --site \u003Curl> --product \u003Cjira\\|confluence> -e development` |\n| Blank panel \u002F Custom UI white screen | Frontend build not run before deploy | `cd static && npm run build && cd .. && forge deploy -e development` |\n| \"Resolver not found\" or resolver returns undefined | Function key in manifest.yml doesn't match resolver registration | Check `manifest.yml` `function.key` matches the key used in `resolver.define('key', ...)` |\n| 403 \u002F \"Permission denied\" \u002F \"Unauthorized\" | OAuth scope missing from manifest | Add scope to `manifest.yml`, then: `forge deploy -e development && forge install --non-interactive --site \u003Curl> --upgrade` |\n| `forge deploy` fails with \"Invalid manifest\" | YAML syntax error in manifest.yml | Run `forge lint`, fix indentation\u002Fsyntax errors |\n| App deployed but module not visible | Wrong product in `forge install`, or tunnel not active | Verify `--product` flag matches app type; restart tunnel if using `forge tunnel` |\n| \"forge: command not found\" | CLI not installed | `npm install -g @forge\u002Fcli` |\n| `ENOENT` or missing files on deploy | `npm install` not run in app directory | `cd \u003Capp-dir> && npm install && forge deploy -e development` |\n| \"Rate limit exceeded\" | Too many API calls in resolver | Add exponential backoff; check for resolver being called in a loop |\n| \"App tunnel disconnected\" | `forge tunnel` connection dropped | Re-run `forge tunnel`; check VPN isn't blocking websocket connections |\n| \"Cannot read properties of undefined\" | API response shape unexpected | Log the full API response; add null checks |\n| 410 Gone \u002F \"deprecated endpoint has been removed\" | Confluence\u002FJira REST API endpoint removed | Migrate to v2 API (see API Migration section below). Redeploy and check logs |\n| `cannot find associated file` (handler path lint error) | Handler path in manifest.yml doesn't match actual file location | Handler path is relative to `src\u002F`. E.g. if resolver is at `src\u002Fresolvers\u002Findex.js`, handler is `resolvers\u002Findex.handler` (not `index.handler` or `src\u002Fresolvers\u002Findex.handler`). See Handler Path Resolution below |\n| `invoke()` returns undefined, no errors in logs | Frontend `invoke('name')` doesn't match `resolver.define('name')` | The invoke name must exactly match the resolver.define name. Check both files — this is a different check than function key in manifest |\n| `Module not found` \u002F doubled path like `src\u002Fsrc\u002F...` on deploy | Handler path includes `src\u002F` prefix, but bundler already resolves from `src\u002F` | Remove `src\u002F` prefix from handler path. Use `resolvers\u002Findex.handler` not `src\u002Fresolvers\u002Findex.handler` |\n| `npm install -g` permission error \u002F cannot install forge globally | No sudo or write access to global npm directory | Use `npx @forge\u002Fcli` as a drop-in replacement for all `forge` commands (lint, deploy, logs, install). No global install needed |\n\n## Handler Path Resolution\n\nThe `handler` field in `manifest.yml` has the format `\u003Cpath>.\u003Cexport>`, where:\n- `\u003Cpath>` is the file path **relative to `src\u002F`** (without `src\u002F` prefix, without file extension)\n- `\u003Cexport>` is the named export from that file\n\n**Examples:**\n\n| Resolver file location | Export in file | Correct handler value |\n|------------------------|---------------|----------------------|\n| `src\u002Fresolvers\u002Findex.js` | `export const handler = ...` | `resolvers\u002Findex.handler` |\n| `src\u002Findex.js` | `export const handler = ...` | `index.handler` |\n| `src\u002Fbackend\u002Fresolver.ts` | `export const run = ...` | `backend\u002Fresolver.run` |\n\n**Common mistakes:**\n- `index.handler` — wrong if the file is in a subdirectory like `src\u002Fresolvers\u002F`\n- `src\u002Fresolvers\u002Findex.handler` — wrong: bundler prefixes `src\u002F` automatically, resulting in `src\u002Fsrc\u002Fresolvers\u002F...`\n- `resolvers\u002Findex.run` — wrong if the file exports `handler` not `run`\n\n**Diagnostic trick:** If `forge lint` reports \"cannot find associated file\" but you're sure the file exists, try `forge deploy --no-verify`. The bundler error message shows the fully resolved path, which reveals whether the path is being doubled or misresolved.\n\n## Invoke Name vs Function Key\n\nThere are **two separate name-matching requirements** for UI Kit resolvers:\n\n1. **manifest.yml `function.key`** must match the `resolver: function:` reference in the module definition\n2. **Frontend `invoke('name')`** must exactly match **`resolver.define('name', ...)`** in the backend\n\nThese 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.\n\n## API Migration (v1 → v2)\n\nAtlassian is progressively deprecating v1 REST API endpoints. When you see a **410 Gone** response:\n\n1. Check `forge logs` for the exact error — it will show which endpoint returned 410\n2. Identify the v2 equivalent:\n   - **URL pattern**: `\u002Fwiki\u002Frest\u002Fapi\u002Fcontent\u002F...` → `\u002Fwiki\u002Fapi\u002Fv2\u002Fpages\u002F...` (or `\u002Fblogposts\u002F...`, `\u002Fspaces\u002F...`)\n   - **Jira**: `\u002Frest\u002Fapi\u002F2\u002F...` → `\u002Frest\u002Fapi\u002F3\u002F...`\n3. Update **pagination**: v2 Confluence APIs use **cursor-based** pagination (`cursor` parameter) instead of offset-based (`start` parameter). The next cursor is in `data._links.next`\n4. Update **response shape**: v2 may return different field names (e.g. `authorId` instead of nested `by.accountId`)\n5. Redeploy and check logs to confirm the fix\n\n**Do NOT** treat 410 as a permissions issue — it means the endpoint no longer exists, not that access is denied.\n\n## Step 8: Cleanup\n\nOnce the issue is resolved:\n\n1. Remove any `console.error('[DEBUG] ...')` statements you added.\n2. Remove verbose flags from any scripts.\n3. Run `forge lint` one final time to confirm clean state.\n4. Redeploy if you modified code during debugging:\n   ```bash\n   forge deploy -e development\n   ```\n5. Confirm the fix works by triggering the app and checking that `forge logs` shows no new errors.\n\n## Escalation\n\nIf none of the above resolves the issue:\n\n- Run `forge logs -e development --verbose --limit 200` for extended output.\n- Check the Forge changelog for known issues: `search-forge-docs \"known issues \u003Cerror-text>\"`\n- If the error is in a Forge platform API (not your code), note the `traceId` from the log output — this is what Atlassian support needs.\n\n## Authentication Errors\n\nIf any command fails with \"not authenticated\" or \"run forge login\":\n\n1. Tell the user to create an API token at **https:\u002F\u002Fid.atlassian.com\u002Fmanage\u002Fapi-tokens**\n2. Tell them to run `forge login` in **their own terminal** (not via the agent) — it will prompt for their email and the API token\n3. Example message: *\"You need to log in. Create an API token at https:\u002F\u002Fid.atlassian.com\u002Fmanage\u002Fapi-tokens, then run `forge login` in your terminal. Enter your Atlassian email and the token when prompted — do not paste the token here.\"*\n4. After they confirm login, resume debugging from where you left off.\n\n## Token Efficiency Rules\n\nFollow these to keep context usage low:\n\n- Read `forge logs` before reading any source file — logs usually reveal the root cause without needing to inspect code.\n- Read only the specific file implicated by the error. Match the error to its file:\n  - `npm ERR! missing script: build` → check only `package.json` (scripts section)\n  - `invalid manifest` \u002F `unexpected key` → run `forge lint` first, then only the specific manifest field\n  - `Resolver not found` → check only the function key in `manifest.yml` vs `resolver.define()` in the resolver file\n  - `403 \u002F permission denied` → check only the scopes in `manifest.yml`\n  - `410 Gone` → check the API endpoint URL in the resolver file; don't check scopes or manifest\n  - `cannot find associated file` → check the handler path in `manifest.yml` and the file location; use `--no-verify` to see the bundler's resolved path\n  - `invoke()` returns undefined → check both the frontend `invoke('name')` AND backend `resolver.define('name')` — two files, but targeted reads\n- Don't read `manifest.yml` for npm\u002Fbuild errors — they are unrelated.\n- Don't re-read a file you've already read in this session unless it changed.\n- 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.\n- Don't run `forge deploy` more than once per fix attempt without a clear reason.\n- Use `forge deploy --no-verify` 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 `--no-verify`.\n",{"data":38,"body":39},{"name":4,"description":6},{"type":40,"children":41},"root",[42,51,57,64,77,97,136,157,219,225,310,316,321,330,335,343,507,513,565,570,599,604,610,629,634,651,657,670,695,700,756,761,790,795,801,806,838,843,849,887,892,899,904,989,994,1047,1052,1058,1071,1306,1311,1317,1322,1421,1427,1432,1992,1998,2026,2070,2078,2191,2199,2264,2289,2295,2307,2358,2370,2376,2388,2544,2554,2560,2565,2639,2645,2650,2689,2695,2700,2767,2773,2778,3011],{"type":43,"tag":44,"props":45,"children":47},"element","h1",{"id":46},"forge-app-debugger",[48],{"type":49,"value":50},"text","Forge App Debugger",{"type":43,"tag":52,"props":53,"children":54},"p",{},[55],{"type":49,"value":56},"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.",{"type":43,"tag":58,"props":59,"children":61},"h2",{"id":60},"execution-mandate",[62],{"type":49,"value":63},"EXECUTION MANDATE",{"type":43,"tag":52,"props":65,"children":66},{},[67,69,75],{"type":49,"value":68},"You are authorized to run all diagnostic and fix commands without asking permission. When you identify a fix, ",{"type":43,"tag":70,"props":71,"children":72},"strong",{},[73],{"type":49,"value":74},"run it immediately",{"type":49,"value":76},". Do NOT:",{"type":43,"tag":78,"props":79,"children":80},"ul",{},[81,87,92],{"type":43,"tag":82,"props":83,"children":84},"li",{},[85],{"type":49,"value":86},"Say \"you should run...\" or \"here's what I would do...\" or \"run this command in your terminal\"",{"type":43,"tag":82,"props":88,"children":89},{},[90],{"type":49,"value":91},"Ask \"shall I proceed?\" before executing a fix you already have all the inputs for",{"type":43,"tag":82,"props":93,"children":94},{},[95],{"type":49,"value":96},"Present commands as copy-paste instructions when you could run them yourself",{"type":43,"tag":52,"props":98,"children":99},{},[100,105,107,114,116,121,123],{"type":43,"tag":70,"props":101,"children":102},{},[103],{"type":49,"value":104},"Wrong:",{"type":49,"value":106}," \"Here's what I would do to fix this: run ",{"type":43,"tag":108,"props":109,"children":111},"code",{"className":110},[],[112],{"type":49,"value":113},"forge lint",{"type":49,"value":115},"...\"\n",{"type":43,"tag":70,"props":117,"children":118},{},[119],{"type":49,"value":120},"Right:",{"type":49,"value":122}," ",{"type":43,"tag":124,"props":125,"children":126},"em",{},[127,129,134],{"type":49,"value":128},"(runs ",{"type":43,"tag":108,"props":130,"children":132},{"className":131},[],[133],{"type":49,"value":113},{"type":49,"value":135}," immediately and reports the result)",{"type":43,"tag":52,"props":137,"children":138},{},[139,141,147,149,155],{"type":49,"value":140},"The only exceptions: commands requiring an interactive terminal (",{"type":43,"tag":108,"props":142,"children":144},{"className":143},[],[145],{"type":49,"value":146},"forge login",{"type":49,"value":148},", ",{"type":43,"tag":108,"props":150,"children":152},{"className":151},[],[153],{"type":49,"value":154},"forge tunnel",{"type":49,"value":156},") must be run by the user in their own terminal — tell them exactly what to run and why.",{"type":43,"tag":52,"props":158,"children":159},{},[160,165,167,173,175,181,183,189,191,197,199,204,206,211,212,217],{"type":43,"tag":70,"props":161,"children":162},{},[163],{"type":49,"value":164},"Attribution:",{"type":49,"value":166}," prefix every ",{"type":43,"tag":108,"props":168,"children":170},{"className":169},[],[171],{"type":49,"value":172},"forge",{"type":49,"value":174}," command you run yourself with ",{"type":43,"tag":108,"props":176,"children":178},{"className":177},[],[179],{"type":49,"value":180},"ATL_FORGE_ATTRIBUTION_SKILL_NAME=forge-debugger",{"type":49,"value":182}," (e.g. ",{"type":43,"tag":108,"props":184,"children":186},{"className":185},[],[187],{"type":49,"value":188},"ATL_FORGE_ATTRIBUTION_SKILL_NAME=forge-debugger forge lint",{"type":49,"value":190},"; with the npx fallback, ",{"type":43,"tag":108,"props":192,"children":194},{"className":193},[],[195],{"type":49,"value":196},"ATL_FORGE_ATTRIBUTION_SKILL_NAME=forge-debugger npx @forge\u002Fcli lint",{"type":49,"value":198},"). The ",{"type":43,"tag":108,"props":200,"children":202},{"className":201},[],[203],{"type":49,"value":172},{"type":49,"value":205}," commands shown later in this skill omit it for readability — add it to each one you run. Never set it on the user-run interactive commands above (",{"type":43,"tag":108,"props":207,"children":209},{"className":208},[],[210],{"type":49,"value":146},{"type":49,"value":148},{"type":43,"tag":108,"props":213,"children":215},{"className":214},[],[216],{"type":49,"value":154},{"type":49,"value":218},").",{"type":43,"tag":58,"props":220,"children":222},{"id":221},"diagnostic-principles",[223],{"type":49,"value":224},"Diagnostic Principles",{"type":43,"tag":78,"props":226,"children":227},{},[228,238,248,265,275,285],{"type":43,"tag":82,"props":229,"children":230},{},[231,236],{"type":43,"tag":70,"props":232,"children":233},{},[234],{"type":49,"value":235},"Cheap first",{"type":49,"value":237},": lint and version checks cost nothing. Run them before reading source code or logs.",{"type":43,"tag":82,"props":239,"children":240},{},[241,246],{"type":43,"tag":70,"props":242,"children":243},{},[244],{"type":49,"value":245},"One action at a time",{"type":49,"value":247},": check the result of each action before taking the next one.",{"type":43,"tag":82,"props":249,"children":250},{},[251,256,258,263],{"type":43,"tag":70,"props":252,"children":253},{},[254],{"type":49,"value":255},"Stop at root cause",{"type":49,"value":257},": once you've identified why something is broken, fix it and stop — don't keep investigating other things. ",{"type":43,"tag":70,"props":259,"children":260},{},[261],{"type":49,"value":262},"Exception",{"type":49,"value":264},": 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.",{"type":43,"tag":82,"props":266,"children":267},{},[268,273],{"type":43,"tag":70,"props":269,"children":270},{},[271],{"type":49,"value":272},"Own the fixes",{"type":49,"value":274},": run the fix commands yourself, don't hand them to the user.",{"type":43,"tag":82,"props":276,"children":277},{},[278,283],{"type":43,"tag":70,"props":279,"children":280},{},[281],{"type":49,"value":282},"Clean up",{"type":49,"value":284},": remove any debug code or verbose flags you added once the issue is resolved.",{"type":43,"tag":82,"props":286,"children":287},{},[288,293,295,300,302,308],{"type":43,"tag":70,"props":289,"children":290},{},[291],{"type":49,"value":292},"npx fallback",{"type":49,"value":294},": if ",{"type":43,"tag":108,"props":296,"children":298},{"className":297},[],[299],{"type":49,"value":172},{"type":49,"value":301}," CLI can't be installed globally (permission errors, no sudo), use ",{"type":43,"tag":108,"props":303,"children":305},{"className":304},[],[306],{"type":49,"value":307},"npx @forge\u002Fcli",{"type":49,"value":309}," as a drop-in replacement for all forge commands.",{"type":43,"tag":58,"props":311,"children":313},{"id":312},"step-1-classify-the-error",[314],{"type":49,"value":315},"Step 1: Classify the Error",{"type":43,"tag":52,"props":317,"children":318},{},[319],{"type":49,"value":320},"Before running any commands, ask one question if the user hasn't made it clear:",{"type":43,"tag":322,"props":323,"children":324},"blockquote",{},[325],{"type":43,"tag":52,"props":326,"children":327},{},[328],{"type":49,"value":329},"\"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)?\"",{"type":43,"tag":52,"props":331,"children":332},{},[333],{"type":49,"value":334},"If obvious from the error message, skip the question and proceed directly.",{"type":43,"tag":52,"props":336,"children":337},{},[338],{"type":43,"tag":70,"props":339,"children":340},{},[341],{"type":49,"value":342},"Quick routing:",{"type":43,"tag":344,"props":345,"children":346},"table",{},[347,366],{"type":43,"tag":348,"props":349,"children":350},"thead",{},[351],{"type":43,"tag":352,"props":353,"children":354},"tr",{},[355,361],{"type":43,"tag":356,"props":357,"children":358},"th",{},[359],{"type":49,"value":360},"Symptom",{"type":43,"tag":356,"props":362,"children":363},{},[364],{"type":49,"value":365},"Go to",{"type":43,"tag":367,"props":368,"children":369},"tbody",{},[370,390,403,416,429,442,455,468,481,494],{"type":43,"tag":352,"props":371,"children":372},{},[373,385],{"type":43,"tag":374,"props":375,"children":376},"td",{},[377,383],{"type":43,"tag":108,"props":378,"children":380},{"className":379},[],[381],{"type":49,"value":382},"forge deploy",{"type":49,"value":384}," fails",{"type":43,"tag":374,"props":386,"children":387},{},[388],{"type":49,"value":389},"Step 2 → 3 → 4",{"type":43,"tag":352,"props":391,"children":392},{},[393,398],{"type":43,"tag":374,"props":394,"children":395},{},[396],{"type":49,"value":397},"App not visible after install",{"type":43,"tag":374,"props":399,"children":400},{},[401],{"type":49,"value":402},"Step 3 → common error: \"App not installed\"",{"type":43,"tag":352,"props":404,"children":405},{},[406,411],{"type":43,"tag":374,"props":407,"children":408},{},[409],{"type":49,"value":410},"App crashes \u002F resolver error",{"type":43,"tag":374,"props":412,"children":413},{},[414],{"type":49,"value":415},"Step 3 → 5 → 6",{"type":43,"tag":352,"props":417,"children":418},{},[419,424],{"type":43,"tag":374,"props":420,"children":421},{},[422],{"type":49,"value":423},"Blank UI \u002F Custom UI not rendering",{"type":43,"tag":374,"props":425,"children":426},{},[427],{"type":49,"value":428},"Step 3 → 4 → common error: \"blank Custom UI\"",{"type":43,"tag":352,"props":430,"children":431},{},[432,437],{"type":43,"tag":374,"props":433,"children":434},{},[435],{"type":49,"value":436},"Works in dev, fails in prod",{"type":43,"tag":374,"props":438,"children":439},{},[440],{"type":49,"value":441},"Step 7 (Production)",{"type":43,"tag":352,"props":443,"children":444},{},[445,450],{"type":43,"tag":374,"props":446,"children":447},{},[448],{"type":49,"value":449},"Permission denied \u002F 403",{"type":43,"tag":374,"props":451,"children":452},{},[453],{"type":49,"value":454},"Common error: \"Permission denied\"",{"type":43,"tag":352,"props":456,"children":457},{},[458,463],{"type":43,"tag":374,"props":459,"children":460},{},[461],{"type":49,"value":462},"410 Gone \u002F deprecated endpoint",{"type":43,"tag":374,"props":464,"children":465},{},[466],{"type":49,"value":467},"Common error: \"410 Gone\" → API Migration section",{"type":43,"tag":352,"props":469,"children":470},{},[471,476],{"type":43,"tag":374,"props":472,"children":473},{},[474],{"type":49,"value":475},"Handler path lint error",{"type":43,"tag":374,"props":477,"children":478},{},[479],{"type":49,"value":480},"Common error: \"cannot find associated file\" → Handler Path Resolution section",{"type":43,"tag":352,"props":482,"children":483},{},[484,489],{"type":43,"tag":374,"props":485,"children":486},{},[487],{"type":49,"value":488},"Resolver returns undefined, no errors",{"type":43,"tag":374,"props":490,"children":491},{},[492],{"type":49,"value":493},"Common error: invoke name mismatch → Invoke Name vs Function Key section",{"type":43,"tag":352,"props":495,"children":496},{},[497,502],{"type":43,"tag":374,"props":498,"children":499},{},[500],{"type":49,"value":501},"Multiple failures (deploy + runtime)",{"type":43,"tag":374,"props":503,"children":504},{},[505],{"type":49,"value":506},"Fix deploy errors first, deploy, then check logs for runtime errors",{"type":43,"tag":58,"props":508,"children":510},{"id":509},"step-2-version-check",[511],{"type":49,"value":512},"Step 2: Version Check",{"type":43,"tag":514,"props":515,"children":520},"pre",{"className":516,"code":517,"language":518,"meta":519,"style":519},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","forge --version\nnpm show @forge\u002Fcli version\n","bash","",[521],{"type":43,"tag":108,"props":522,"children":523},{"__ignoreMap":519},[524,541],{"type":43,"tag":525,"props":526,"children":529},"span",{"class":527,"line":528},"line",1,[530,535],{"type":43,"tag":525,"props":531,"children":533},{"style":532},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[534],{"type":49,"value":172},{"type":43,"tag":525,"props":536,"children":538},{"style":537},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[539],{"type":49,"value":540}," --version\n",{"type":43,"tag":525,"props":542,"children":544},{"class":527,"line":543},2,[545,550,555,560],{"type":43,"tag":525,"props":546,"children":547},{"style":532},[548],{"type":49,"value":549},"npm",{"type":43,"tag":525,"props":551,"children":552},{"style":537},[553],{"type":49,"value":554}," show",{"type":43,"tag":525,"props":556,"children":557},{"style":537},[558],{"type":49,"value":559}," @forge\u002Fcli",{"type":43,"tag":525,"props":561,"children":562},{"style":537},[563],{"type":49,"value":564}," version\n",{"type":43,"tag":52,"props":566,"children":567},{},[568],{"type":49,"value":569},"If the installed version is behind the latest major version, upgrade immediately:",{"type":43,"tag":514,"props":571,"children":573},{"className":516,"code":572,"language":518,"meta":519,"style":519},"npm install -g @forge\u002Fcli\n",[574],{"type":43,"tag":108,"props":575,"children":576},{"__ignoreMap":519},[577],{"type":43,"tag":525,"props":578,"children":579},{"class":527,"line":528},[580,584,589,594],{"type":43,"tag":525,"props":581,"children":582},{"style":532},[583],{"type":49,"value":549},{"type":43,"tag":525,"props":585,"children":586},{"style":537},[587],{"type":49,"value":588}," install",{"type":43,"tag":525,"props":590,"children":591},{"style":537},[592],{"type":49,"value":593}," -g",{"type":43,"tag":525,"props":595,"children":596},{"style":537},[597],{"type":49,"value":598}," @forge\u002Fcli\n",{"type":43,"tag":52,"props":600,"children":601},{},[602],{"type":49,"value":603},"Then retry the failing operation. Many bugs are fixed in newer CLI versions.",{"type":43,"tag":58,"props":605,"children":607},{"id":606},"step-3-lint",[608],{"type":49,"value":609},"Step 3: Lint",{"type":43,"tag":514,"props":611,"children":613},{"className":516,"code":612,"language":518,"meta":519,"style":519},"forge lint\n",[614],{"type":43,"tag":108,"props":615,"children":616},{"__ignoreMap":519},[617],{"type":43,"tag":525,"props":618,"children":619},{"class":527,"line":528},[620,624],{"type":43,"tag":525,"props":621,"children":622},{"style":532},[623],{"type":49,"value":172},{"type":43,"tag":525,"props":625,"children":626},{"style":537},[627],{"type":49,"value":628}," lint\n",{"type":43,"tag":52,"props":630,"children":631},{},[632],{"type":49,"value":633},"Fix every error before proceeding — lint errors cause deploy failures and silent runtime bugs. If lint passes cleanly, continue to the next step.",{"type":43,"tag":52,"props":635,"children":636},{},[637,642,644,649],{"type":43,"tag":70,"props":638,"children":639},{},[640],{"type":49,"value":641},"For any manifest-related error message",{"type":49,"value":643}," (e.g. \"invalid manifest\", \"unexpected key\", \"modules.jira:*\" errors): run ",{"type":43,"tag":108,"props":645,"children":647},{"className":646},[],[648],{"type":49,"value":113},{"type":49,"value":650}," 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.",{"type":43,"tag":58,"props":652,"children":654},{"id":653},"step-4-custom-ui-build-check",[655],{"type":49,"value":656},"Step 4: Custom UI Build Check",{"type":43,"tag":52,"props":658,"children":659},{},[660,662,668],{"type":49,"value":661},"Only applies when the app has a ",{"type":43,"tag":108,"props":663,"children":665},{"className":664},[],[666],{"type":49,"value":667},"static\u002F",{"type":49,"value":669}," directory (Custom UI apps). Check if the frontend was built before the last deploy:",{"type":43,"tag":514,"props":671,"children":673},{"className":516,"code":672,"language":518,"meta":519,"style":519},"ls -la static\u002Fbuild\u002F\n",[674],{"type":43,"tag":108,"props":675,"children":676},{"__ignoreMap":519},[677],{"type":43,"tag":525,"props":678,"children":679},{"class":527,"line":528},[680,685,690],{"type":43,"tag":525,"props":681,"children":682},{"style":532},[683],{"type":49,"value":684},"ls",{"type":43,"tag":525,"props":686,"children":687},{"style":537},[688],{"type":49,"value":689}," -la",{"type":43,"tag":525,"props":691,"children":692},{"style":537},[693],{"type":49,"value":694}," static\u002Fbuild\u002F\n",{"type":43,"tag":52,"props":696,"children":697},{},[698],{"type":49,"value":699},"If the build directory is missing or older than recent source changes, rebuild:",{"type":43,"tag":514,"props":701,"children":703},{"className":516,"code":702,"language":518,"meta":519,"style":519},"cd static && npm run build && cd ..\n",[704],{"type":43,"tag":108,"props":705,"children":706},{"__ignoreMap":519},[707],{"type":43,"tag":525,"props":708,"children":709},{"class":527,"line":528},[710,716,721,727,732,737,742,746,751],{"type":43,"tag":525,"props":711,"children":713},{"style":712},"--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF",[714],{"type":49,"value":715},"cd",{"type":43,"tag":525,"props":717,"children":718},{"style":537},[719],{"type":49,"value":720}," static",{"type":43,"tag":525,"props":722,"children":724},{"style":723},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[725],{"type":49,"value":726}," &&",{"type":43,"tag":525,"props":728,"children":729},{"style":532},[730],{"type":49,"value":731}," npm",{"type":43,"tag":525,"props":733,"children":734},{"style":537},[735],{"type":49,"value":736}," run",{"type":43,"tag":525,"props":738,"children":739},{"style":537},[740],{"type":49,"value":741}," build",{"type":43,"tag":525,"props":743,"children":744},{"style":723},[745],{"type":49,"value":726},{"type":43,"tag":525,"props":747,"children":748},{"style":712},[749],{"type":49,"value":750}," cd",{"type":43,"tag":525,"props":752,"children":753},{"style":537},[754],{"type":49,"value":755}," ..\n",{"type":43,"tag":52,"props":757,"children":758},{},[759],{"type":49,"value":760},"Then redeploy:",{"type":43,"tag":514,"props":762,"children":764},{"className":516,"code":763,"language":518,"meta":519,"style":519},"forge deploy -e development\n",[765],{"type":43,"tag":108,"props":766,"children":767},{"__ignoreMap":519},[768],{"type":43,"tag":525,"props":769,"children":770},{"class":527,"line":528},[771,775,780,785],{"type":43,"tag":525,"props":772,"children":773},{"style":532},[774],{"type":49,"value":172},{"type":43,"tag":525,"props":776,"children":777},{"style":537},[778],{"type":49,"value":779}," deploy",{"type":43,"tag":525,"props":781,"children":782},{"style":537},[783],{"type":49,"value":784}," -e",{"type":43,"tag":525,"props":786,"children":787},{"style":537},[788],{"type":49,"value":789}," development\n",{"type":43,"tag":52,"props":791,"children":792},{},[793],{"type":49,"value":794},"This is one of the most common causes of blank UI panels.",{"type":43,"tag":58,"props":796,"children":798},{"id":797},"step-5-deploy-status",[799],{"type":49,"value":800},"Step 5: Deploy Status",{"type":43,"tag":52,"props":802,"children":803},{},[804],{"type":49,"value":805},"Verify the app was actually deployed successfully:",{"type":43,"tag":514,"props":807,"children":809},{"className":516,"code":808,"language":518,"meta":519,"style":519},"forge deploy -e development --verbose\n",[810],{"type":43,"tag":108,"props":811,"children":812},{"__ignoreMap":519},[813],{"type":43,"tag":525,"props":814,"children":815},{"class":527,"line":528},[816,820,824,828,833],{"type":43,"tag":525,"props":817,"children":818},{"style":532},[819],{"type":49,"value":172},{"type":43,"tag":525,"props":821,"children":822},{"style":537},[823],{"type":49,"value":779},{"type":43,"tag":525,"props":825,"children":826},{"style":537},[827],{"type":49,"value":784},{"type":43,"tag":525,"props":829,"children":830},{"style":537},[831],{"type":49,"value":832}," development",{"type":43,"tag":525,"props":834,"children":835},{"style":537},[836],{"type":49,"value":837}," --verbose\n",{"type":43,"tag":52,"props":839,"children":840},{},[841],{"type":49,"value":842},"Watch 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.",{"type":43,"tag":58,"props":844,"children":846},{"id":845},"step-6-logs",[847],{"type":49,"value":848},"Step 6: Logs",{"type":43,"tag":514,"props":850,"children":852},{"className":516,"code":851,"language":518,"meta":519,"style":519},"forge logs -e development --limit 100\n",[853],{"type":43,"tag":108,"props":854,"children":855},{"__ignoreMap":519},[856],{"type":43,"tag":525,"props":857,"children":858},{"class":527,"line":528},[859,863,868,872,876,881],{"type":43,"tag":525,"props":860,"children":861},{"style":532},[862],{"type":49,"value":172},{"type":43,"tag":525,"props":864,"children":865},{"style":537},[866],{"type":49,"value":867}," logs",{"type":43,"tag":525,"props":869,"children":870},{"style":537},[871],{"type":49,"value":784},{"type":43,"tag":525,"props":873,"children":874},{"style":537},[875],{"type":49,"value":832},{"type":43,"tag":525,"props":877,"children":878},{"style":537},[879],{"type":49,"value":880}," --limit",{"type":43,"tag":525,"props":882,"children":884},{"style":883},"--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C",[885],{"type":49,"value":886}," 100\n",{"type":43,"tag":52,"props":888,"children":889},{},[890],{"type":49,"value":891},"Read the logs carefully. Most runtime errors appear here.",{"type":43,"tag":893,"props":894,"children":896},"h3",{"id":895},"if-no-logs-are-returned",[897],{"type":49,"value":898},"If no logs are returned",{"type":43,"tag":52,"props":900,"children":901},{},[902],{"type":49,"value":903},"The resolver may not have been triggered, or logging isn't set up. Add a debug log at the entry point of the resolver:",{"type":43,"tag":514,"props":905,"children":909},{"className":906,"code":907,"language":908,"meta":519,"style":519},"language-javascript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F Add at the top of your handler function:\nconsole.error('[DEBUG] Handler called with:', JSON.stringify(payload));\n","javascript",[910],{"type":43,"tag":108,"props":911,"children":912},{"__ignoreMap":519},[913,922],{"type":43,"tag":525,"props":914,"children":915},{"class":527,"line":528},[916],{"type":43,"tag":525,"props":917,"children":919},{"style":918},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic",[920],{"type":49,"value":921},"\u002F\u002F Add at the top of your handler function:\n",{"type":43,"tag":525,"props":923,"children":924},{"class":527,"line":543},[925,931,936,941,946,951,956,960,965,970,974,979,984],{"type":43,"tag":525,"props":926,"children":928},{"style":927},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[929],{"type":49,"value":930},"console",{"type":43,"tag":525,"props":932,"children":933},{"style":723},[934],{"type":49,"value":935},".",{"type":43,"tag":525,"props":937,"children":938},{"style":712},[939],{"type":49,"value":940},"error",{"type":43,"tag":525,"props":942,"children":943},{"style":927},[944],{"type":49,"value":945},"(",{"type":43,"tag":525,"props":947,"children":948},{"style":723},[949],{"type":49,"value":950},"'",{"type":43,"tag":525,"props":952,"children":953},{"style":537},[954],{"type":49,"value":955},"[DEBUG] Handler called with:",{"type":43,"tag":525,"props":957,"children":958},{"style":723},[959],{"type":49,"value":950},{"type":43,"tag":525,"props":961,"children":962},{"style":723},[963],{"type":49,"value":964},",",{"type":43,"tag":525,"props":966,"children":967},{"style":927},[968],{"type":49,"value":969}," JSON",{"type":43,"tag":525,"props":971,"children":972},{"style":723},[973],{"type":49,"value":935},{"type":43,"tag":525,"props":975,"children":976},{"style":712},[977],{"type":49,"value":978},"stringify",{"type":43,"tag":525,"props":980,"children":981},{"style":927},[982],{"type":49,"value":983},"(payload))",{"type":43,"tag":525,"props":985,"children":986},{"style":723},[987],{"type":49,"value":988},";\n",{"type":43,"tag":52,"props":990,"children":991},{},[992],{"type":49,"value":993},"Then redeploy and trigger the app again:",{"type":43,"tag":514,"props":995,"children":997},{"className":516,"code":996,"language":518,"meta":519,"style":519},"forge deploy -e development\nforge logs -e development --limit 100\n",[998],{"type":43,"tag":108,"props":999,"children":1000},{"__ignoreMap":519},[1001,1020],{"type":43,"tag":525,"props":1002,"children":1003},{"class":527,"line":528},[1004,1008,1012,1016],{"type":43,"tag":525,"props":1005,"children":1006},{"style":532},[1007],{"type":49,"value":172},{"type":43,"tag":525,"props":1009,"children":1010},{"style":537},[1011],{"type":49,"value":779},{"type":43,"tag":525,"props":1013,"children":1014},{"style":537},[1015],{"type":49,"value":784},{"type":43,"tag":525,"props":1017,"children":1018},{"style":537},[1019],{"type":49,"value":789},{"type":43,"tag":525,"props":1021,"children":1022},{"class":527,"line":543},[1023,1027,1031,1035,1039,1043],{"type":43,"tag":525,"props":1024,"children":1025},{"style":532},[1026],{"type":49,"value":172},{"type":43,"tag":525,"props":1028,"children":1029},{"style":537},[1030],{"type":49,"value":867},{"type":43,"tag":525,"props":1032,"children":1033},{"style":537},[1034],{"type":49,"value":784},{"type":43,"tag":525,"props":1036,"children":1037},{"style":537},[1038],{"type":49,"value":832},{"type":43,"tag":525,"props":1040,"children":1041},{"style":537},[1042],{"type":49,"value":880},{"type":43,"tag":525,"props":1044,"children":1045},{"style":883},[1046],{"type":49,"value":886},{"type":43,"tag":52,"props":1048,"children":1049},{},[1050],{"type":49,"value":1051},"Remove the debug log after you've identified the issue.",{"type":43,"tag":893,"props":1053,"children":1055},{"id":1054},"if-the-error-is-in-the-frontend-ui-rendering-blank-screen",[1056],{"type":49,"value":1057},"If the error is in the frontend (UI rendering, blank screen)",{"type":43,"tag":52,"props":1059,"children":1060},{},[1061,1063,1069],{"type":49,"value":1062},"Forge UI Kit errors surface in ",{"type":43,"tag":108,"props":1064,"children":1066},{"className":1065},[],[1067],{"type":49,"value":1068},"forge logs",{"type":49,"value":1070},", not the browser console. For Custom UI, add error logging in the resolver that backs the UI:",{"type":43,"tag":514,"props":1072,"children":1074},{"className":906,"code":1073,"language":908,"meta":519,"style":519},"try {\n  const result = await api.asUser().requestJira(\u002F* ... *\u002F);\n  return result;\n} catch (err) {\n  console.error('[DEBUG] Resolver error:', err.message, err.stack);\n  throw err;\n}\n",[1075],{"type":43,"tag":108,"props":1076,"children":1077},{"__ignoreMap":519},[1078,1092,1163,1180,1204,1281,1298],{"type":43,"tag":525,"props":1079,"children":1080},{"class":527,"line":528},[1081,1087],{"type":43,"tag":525,"props":1082,"children":1084},{"style":1083},"--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic",[1085],{"type":49,"value":1086},"try",{"type":43,"tag":525,"props":1088,"children":1089},{"style":723},[1090],{"type":49,"value":1091}," {\n",{"type":43,"tag":525,"props":1093,"children":1094},{"class":527,"line":543},[1095,1101,1106,1111,1116,1121,1125,1130,1136,1140,1145,1149,1154,1159],{"type":43,"tag":525,"props":1096,"children":1098},{"style":1097},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA",[1099],{"type":49,"value":1100},"  const",{"type":43,"tag":525,"props":1102,"children":1103},{"style":927},[1104],{"type":49,"value":1105}," result",{"type":43,"tag":525,"props":1107,"children":1108},{"style":723},[1109],{"type":49,"value":1110}," =",{"type":43,"tag":525,"props":1112,"children":1113},{"style":1083},[1114],{"type":49,"value":1115}," await",{"type":43,"tag":525,"props":1117,"children":1118},{"style":927},[1119],{"type":49,"value":1120}," api",{"type":43,"tag":525,"props":1122,"children":1123},{"style":723},[1124],{"type":49,"value":935},{"type":43,"tag":525,"props":1126,"children":1127},{"style":712},[1128],{"type":49,"value":1129},"asUser",{"type":43,"tag":525,"props":1131,"children":1133},{"style":1132},"--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178",[1134],{"type":49,"value":1135},"()",{"type":43,"tag":525,"props":1137,"children":1138},{"style":723},[1139],{"type":49,"value":935},{"type":43,"tag":525,"props":1141,"children":1142},{"style":712},[1143],{"type":49,"value":1144},"requestJira",{"type":43,"tag":525,"props":1146,"children":1147},{"style":1132},[1148],{"type":49,"value":945},{"type":43,"tag":525,"props":1150,"children":1151},{"style":918},[1152],{"type":49,"value":1153},"\u002F* ... *\u002F",{"type":43,"tag":525,"props":1155,"children":1156},{"style":1132},[1157],{"type":49,"value":1158},")",{"type":43,"tag":525,"props":1160,"children":1161},{"style":723},[1162],{"type":49,"value":988},{"type":43,"tag":525,"props":1164,"children":1166},{"class":527,"line":1165},3,[1167,1172,1176],{"type":43,"tag":525,"props":1168,"children":1169},{"style":1083},[1170],{"type":49,"value":1171},"  return",{"type":43,"tag":525,"props":1173,"children":1174},{"style":927},[1175],{"type":49,"value":1105},{"type":43,"tag":525,"props":1177,"children":1178},{"style":723},[1179],{"type":49,"value":988},{"type":43,"tag":525,"props":1181,"children":1183},{"class":527,"line":1182},4,[1184,1189,1194,1199],{"type":43,"tag":525,"props":1185,"children":1186},{"style":723},[1187],{"type":49,"value":1188},"}",{"type":43,"tag":525,"props":1190,"children":1191},{"style":1083},[1192],{"type":49,"value":1193}," catch",{"type":43,"tag":525,"props":1195,"children":1196},{"style":927},[1197],{"type":49,"value":1198}," (err) ",{"type":43,"tag":525,"props":1200,"children":1201},{"style":723},[1202],{"type":49,"value":1203},"{\n",{"type":43,"tag":525,"props":1205,"children":1207},{"class":527,"line":1206},5,[1208,1213,1217,1221,1225,1229,1234,1238,1242,1247,1251,1256,1260,1264,1268,1273,1277],{"type":43,"tag":525,"props":1209,"children":1210},{"style":927},[1211],{"type":49,"value":1212},"  console",{"type":43,"tag":525,"props":1214,"children":1215},{"style":723},[1216],{"type":49,"value":935},{"type":43,"tag":525,"props":1218,"children":1219},{"style":712},[1220],{"type":49,"value":940},{"type":43,"tag":525,"props":1222,"children":1223},{"style":1132},[1224],{"type":49,"value":945},{"type":43,"tag":525,"props":1226,"children":1227},{"style":723},[1228],{"type":49,"value":950},{"type":43,"tag":525,"props":1230,"children":1231},{"style":537},[1232],{"type":49,"value":1233},"[DEBUG] Resolver error:",{"type":43,"tag":525,"props":1235,"children":1236},{"style":723},[1237],{"type":49,"value":950},{"type":43,"tag":525,"props":1239,"children":1240},{"style":723},[1241],{"type":49,"value":964},{"type":43,"tag":525,"props":1243,"children":1244},{"style":927},[1245],{"type":49,"value":1246}," err",{"type":43,"tag":525,"props":1248,"children":1249},{"style":723},[1250],{"type":49,"value":935},{"type":43,"tag":525,"props":1252,"children":1253},{"style":927},[1254],{"type":49,"value":1255},"message",{"type":43,"tag":525,"props":1257,"children":1258},{"style":723},[1259],{"type":49,"value":964},{"type":43,"tag":525,"props":1261,"children":1262},{"style":927},[1263],{"type":49,"value":1246},{"type":43,"tag":525,"props":1265,"children":1266},{"style":723},[1267],{"type":49,"value":935},{"type":43,"tag":525,"props":1269,"children":1270},{"style":927},[1271],{"type":49,"value":1272},"stack",{"type":43,"tag":525,"props":1274,"children":1275},{"style":1132},[1276],{"type":49,"value":1158},{"type":43,"tag":525,"props":1278,"children":1279},{"style":723},[1280],{"type":49,"value":988},{"type":43,"tag":525,"props":1282,"children":1284},{"class":527,"line":1283},6,[1285,1290,1294],{"type":43,"tag":525,"props":1286,"children":1287},{"style":1083},[1288],{"type":49,"value":1289},"  throw",{"type":43,"tag":525,"props":1291,"children":1292},{"style":927},[1293],{"type":49,"value":1246},{"type":43,"tag":525,"props":1295,"children":1296},{"style":723},[1297],{"type":49,"value":988},{"type":43,"tag":525,"props":1299,"children":1300},{"class":527,"line":24},[1301],{"type":43,"tag":525,"props":1302,"children":1303},{"style":723},[1304],{"type":49,"value":1305},"}\n",{"type":43,"tag":52,"props":1307,"children":1308},{},[1309],{"type":49,"value":1310},"Redeploy, trigger, and check logs.",{"type":43,"tag":58,"props":1312,"children":1314},{"id":1313},"step-7-production-issues",[1315],{"type":49,"value":1316},"Step 7: Production Issues",{"type":43,"tag":52,"props":1318,"children":1319},{},[1320],{"type":49,"value":1321},"If the user reports an issue that only happens in production (or on a specific customer's site):",{"type":43,"tag":1323,"props":1324,"children":1325},"ol",{},[1326,1339,1404,1409],{"type":43,"tag":82,"props":1327,"children":1328},{},[1329,1331,1337],{"type":49,"value":1330},"Ask: \"Which Atlassian site is affected? (e.g. ",{"type":43,"tag":108,"props":1332,"children":1334},{"className":1333},[],[1335],{"type":49,"value":1336},"customername.atlassian.net",{"type":49,"value":1338},")\"",{"type":43,"tag":82,"props":1340,"children":1341},{},[1342,1344],{"type":49,"value":1343},"Check production logs:\n",{"type":43,"tag":514,"props":1345,"children":1347},{"className":516,"code":1346,"language":518,"meta":519,"style":519},"forge logs -e production --site \u003Ccustomer-site> --limit 100\n",[1348],{"type":43,"tag":108,"props":1349,"children":1350},{"__ignoreMap":519},[1351],{"type":43,"tag":525,"props":1352,"children":1353},{"class":527,"line":528},[1354,1358,1362,1366,1371,1376,1381,1386,1391,1396,1400],{"type":43,"tag":525,"props":1355,"children":1356},{"style":532},[1357],{"type":49,"value":172},{"type":43,"tag":525,"props":1359,"children":1360},{"style":537},[1361],{"type":49,"value":867},{"type":43,"tag":525,"props":1363,"children":1364},{"style":537},[1365],{"type":49,"value":784},{"type":43,"tag":525,"props":1367,"children":1368},{"style":537},[1369],{"type":49,"value":1370}," production",{"type":43,"tag":525,"props":1372,"children":1373},{"style":537},[1374],{"type":49,"value":1375}," --site",{"type":43,"tag":525,"props":1377,"children":1378},{"style":723},[1379],{"type":49,"value":1380}," \u003C",{"type":43,"tag":525,"props":1382,"children":1383},{"style":537},[1384],{"type":49,"value":1385},"customer-sit",{"type":43,"tag":525,"props":1387,"children":1388},{"style":927},[1389],{"type":49,"value":1390},"e",{"type":43,"tag":525,"props":1392,"children":1393},{"style":723},[1394],{"type":49,"value":1395},">",{"type":43,"tag":525,"props":1397,"children":1398},{"style":537},[1399],{"type":49,"value":880},{"type":43,"tag":525,"props":1401,"children":1402},{"style":883},[1403],{"type":49,"value":886},{"type":43,"tag":82,"props":1405,"children":1406},{},[1407],{"type":49,"value":1408},"Note: production logs may be delayed up to 2 minutes after the event.",{"type":43,"tag":82,"props":1410,"children":1411},{},[1412,1414,1420],{"type":49,"value":1413},"If the issue is permission-related, check whether scopes were upgraded after a new install — production installs require explicit ",{"type":43,"tag":108,"props":1415,"children":1417},{"className":1416},[],[1418],{"type":49,"value":1419},"--upgrade",{"type":49,"value":935},{"type":43,"tag":58,"props":1422,"children":1424},{"id":1423},"common-error-patterns",[1425],{"type":49,"value":1426},"Common Error Patterns",{"type":43,"tag":52,"props":1428,"children":1429},{},[1430],{"type":49,"value":1431},"Match the error against this table first. If you find a match, apply the fix directly without further investigation.",{"type":43,"tag":344,"props":1433,"children":1434},{},[1435,1456],{"type":43,"tag":348,"props":1436,"children":1437},{},[1438],{"type":43,"tag":352,"props":1439,"children":1440},{},[1441,1446,1451],{"type":43,"tag":356,"props":1442,"children":1443},{},[1444],{"type":49,"value":1445},"Error \u002F Symptom",{"type":43,"tag":356,"props":1447,"children":1448},{},[1449],{"type":49,"value":1450},"Root Cause",{"type":43,"tag":356,"props":1452,"children":1453},{},[1454],{"type":49,"value":1455},"Fix",{"type":43,"tag":367,"props":1457,"children":1458},{},[1459,1489,1511,1550,1581,1611,1649,1671,1705,1723,1753,1771,1789,1853,1891,1954],{"type":43,"tag":352,"props":1460,"children":1461},{},[1462,1467,1478],{"type":43,"tag":374,"props":1463,"children":1464},{},[1465],{"type":49,"value":1466},"\"App is not installed on this site\"",{"type":43,"tag":374,"props":1468,"children":1469},{},[1470,1476],{"type":43,"tag":108,"props":1471,"children":1473},{"className":1472},[],[1474],{"type":49,"value":1475},"forge install",{"type":49,"value":1477}," wasn't run, or ran against wrong site",{"type":43,"tag":374,"props":1479,"children":1480},{},[1481,1483],{"type":49,"value":1482},"Ask for the Atlassian site URL if not already known, then run it yourself: ",{"type":43,"tag":108,"props":1484,"children":1486},{"className":1485},[],[1487],{"type":49,"value":1488},"forge install --non-interactive --site \u003Curl> --product \u003Cjira|confluence> -e development",{"type":43,"tag":352,"props":1490,"children":1491},{},[1492,1497,1502],{"type":43,"tag":374,"props":1493,"children":1494},{},[1495],{"type":49,"value":1496},"Blank panel \u002F Custom UI white screen",{"type":43,"tag":374,"props":1498,"children":1499},{},[1500],{"type":49,"value":1501},"Frontend build not run before deploy",{"type":43,"tag":374,"props":1503,"children":1504},{},[1505],{"type":43,"tag":108,"props":1506,"children":1508},{"className":1507},[],[1509],{"type":49,"value":1510},"cd static && npm run build && cd .. && forge deploy -e development",{"type":43,"tag":352,"props":1512,"children":1513},{},[1514,1519,1524],{"type":43,"tag":374,"props":1515,"children":1516},{},[1517],{"type":49,"value":1518},"\"Resolver not found\" or resolver returns undefined",{"type":43,"tag":374,"props":1520,"children":1521},{},[1522],{"type":49,"value":1523},"Function key in manifest.yml doesn't match resolver registration",{"type":43,"tag":374,"props":1525,"children":1526},{},[1527,1529,1535,1536,1542,1544],{"type":49,"value":1528},"Check ",{"type":43,"tag":108,"props":1530,"children":1532},{"className":1531},[],[1533],{"type":49,"value":1534},"manifest.yml",{"type":49,"value":122},{"type":43,"tag":108,"props":1537,"children":1539},{"className":1538},[],[1540],{"type":49,"value":1541},"function.key",{"type":49,"value":1543}," matches the key used in ",{"type":43,"tag":108,"props":1545,"children":1547},{"className":1546},[],[1548],{"type":49,"value":1549},"resolver.define('key', ...)",{"type":43,"tag":352,"props":1551,"children":1552},{},[1553,1558,1563],{"type":43,"tag":374,"props":1554,"children":1555},{},[1556],{"type":49,"value":1557},"403 \u002F \"Permission denied\" \u002F \"Unauthorized\"",{"type":43,"tag":374,"props":1559,"children":1560},{},[1561],{"type":49,"value":1562},"OAuth scope missing from manifest",{"type":43,"tag":374,"props":1564,"children":1565},{},[1566,1568,1573,1575],{"type":49,"value":1567},"Add scope to ",{"type":43,"tag":108,"props":1569,"children":1571},{"className":1570},[],[1572],{"type":49,"value":1534},{"type":49,"value":1574},", then: ",{"type":43,"tag":108,"props":1576,"children":1578},{"className":1577},[],[1579],{"type":49,"value":1580},"forge deploy -e development && forge install --non-interactive --site \u003Curl> --upgrade",{"type":43,"tag":352,"props":1582,"children":1583},{},[1584,1594,1599],{"type":43,"tag":374,"props":1585,"children":1586},{},[1587,1592],{"type":43,"tag":108,"props":1588,"children":1590},{"className":1589},[],[1591],{"type":49,"value":382},{"type":49,"value":1593}," fails with \"Invalid manifest\"",{"type":43,"tag":374,"props":1595,"children":1596},{},[1597],{"type":49,"value":1598},"YAML syntax error in manifest.yml",{"type":43,"tag":374,"props":1600,"children":1601},{},[1602,1604,1609],{"type":49,"value":1603},"Run ",{"type":43,"tag":108,"props":1605,"children":1607},{"className":1606},[],[1608],{"type":49,"value":113},{"type":49,"value":1610},", fix indentation\u002Fsyntax errors",{"type":43,"tag":352,"props":1612,"children":1613},{},[1614,1619,1631],{"type":43,"tag":374,"props":1615,"children":1616},{},[1617],{"type":49,"value":1618},"App deployed but module not visible",{"type":43,"tag":374,"props":1620,"children":1621},{},[1622,1624,1629],{"type":49,"value":1623},"Wrong product in ",{"type":43,"tag":108,"props":1625,"children":1627},{"className":1626},[],[1628],{"type":49,"value":1475},{"type":49,"value":1630},", or tunnel not active",{"type":43,"tag":374,"props":1632,"children":1633},{},[1634,1636,1642,1644],{"type":49,"value":1635},"Verify ",{"type":43,"tag":108,"props":1637,"children":1639},{"className":1638},[],[1640],{"type":49,"value":1641},"--product",{"type":49,"value":1643}," flag matches app type; restart tunnel if using ",{"type":43,"tag":108,"props":1645,"children":1647},{"className":1646},[],[1648],{"type":49,"value":154},{"type":43,"tag":352,"props":1650,"children":1651},{},[1652,1657,1662],{"type":43,"tag":374,"props":1653,"children":1654},{},[1655],{"type":49,"value":1656},"\"forge: command not found\"",{"type":43,"tag":374,"props":1658,"children":1659},{},[1660],{"type":49,"value":1661},"CLI not installed",{"type":43,"tag":374,"props":1663,"children":1664},{},[1665],{"type":43,"tag":108,"props":1666,"children":1668},{"className":1667},[],[1669],{"type":49,"value":1670},"npm install -g @forge\u002Fcli",{"type":43,"tag":352,"props":1672,"children":1673},{},[1674,1685,1696],{"type":43,"tag":374,"props":1675,"children":1676},{},[1677,1683],{"type":43,"tag":108,"props":1678,"children":1680},{"className":1679},[],[1681],{"type":49,"value":1682},"ENOENT",{"type":49,"value":1684}," or missing files on deploy",{"type":43,"tag":374,"props":1686,"children":1687},{},[1688,1694],{"type":43,"tag":108,"props":1689,"children":1691},{"className":1690},[],[1692],{"type":49,"value":1693},"npm install",{"type":49,"value":1695}," not run in app directory",{"type":43,"tag":374,"props":1697,"children":1698},{},[1699],{"type":43,"tag":108,"props":1700,"children":1702},{"className":1701},[],[1703],{"type":49,"value":1704},"cd \u003Capp-dir> && npm install && forge deploy -e development",{"type":43,"tag":352,"props":1706,"children":1707},{},[1708,1713,1718],{"type":43,"tag":374,"props":1709,"children":1710},{},[1711],{"type":49,"value":1712},"\"Rate limit exceeded\"",{"type":43,"tag":374,"props":1714,"children":1715},{},[1716],{"type":49,"value":1717},"Too many API calls in resolver",{"type":43,"tag":374,"props":1719,"children":1720},{},[1721],{"type":49,"value":1722},"Add exponential backoff; check for resolver being called in a loop",{"type":43,"tag":352,"props":1724,"children":1725},{},[1726,1731,1741],{"type":43,"tag":374,"props":1727,"children":1728},{},[1729],{"type":49,"value":1730},"\"App tunnel disconnected\"",{"type":43,"tag":374,"props":1732,"children":1733},{},[1734,1739],{"type":43,"tag":108,"props":1735,"children":1737},{"className":1736},[],[1738],{"type":49,"value":154},{"type":49,"value":1740}," connection dropped",{"type":43,"tag":374,"props":1742,"children":1743},{},[1744,1746,1751],{"type":49,"value":1745},"Re-run ",{"type":43,"tag":108,"props":1747,"children":1749},{"className":1748},[],[1750],{"type":49,"value":154},{"type":49,"value":1752},"; check VPN isn't blocking websocket connections",{"type":43,"tag":352,"props":1754,"children":1755},{},[1756,1761,1766],{"type":43,"tag":374,"props":1757,"children":1758},{},[1759],{"type":49,"value":1760},"\"Cannot read properties of undefined\"",{"type":43,"tag":374,"props":1762,"children":1763},{},[1764],{"type":49,"value":1765},"API response shape unexpected",{"type":43,"tag":374,"props":1767,"children":1768},{},[1769],{"type":49,"value":1770},"Log the full API response; add null checks",{"type":43,"tag":352,"props":1772,"children":1773},{},[1774,1779,1784],{"type":43,"tag":374,"props":1775,"children":1776},{},[1777],{"type":49,"value":1778},"410 Gone \u002F \"deprecated endpoint has been removed\"",{"type":43,"tag":374,"props":1780,"children":1781},{},[1782],{"type":49,"value":1783},"Confluence\u002FJira REST API endpoint removed",{"type":43,"tag":374,"props":1785,"children":1786},{},[1787],{"type":49,"value":1788},"Migrate to v2 API (see API Migration section below). Redeploy and check logs",{"type":43,"tag":352,"props":1790,"children":1791},{},[1792,1803,1808],{"type":43,"tag":374,"props":1793,"children":1794},{},[1795,1801],{"type":43,"tag":108,"props":1796,"children":1798},{"className":1797},[],[1799],{"type":49,"value":1800},"cannot find associated file",{"type":49,"value":1802}," (handler path lint error)",{"type":43,"tag":374,"props":1804,"children":1805},{},[1806],{"type":49,"value":1807},"Handler path in manifest.yml doesn't match actual file location",{"type":43,"tag":374,"props":1809,"children":1810},{},[1811,1813,1819,1821,1827,1829,1835,1837,1843,1845,1851],{"type":49,"value":1812},"Handler path is relative to ",{"type":43,"tag":108,"props":1814,"children":1816},{"className":1815},[],[1817],{"type":49,"value":1818},"src\u002F",{"type":49,"value":1820},". E.g. if resolver is at ",{"type":43,"tag":108,"props":1822,"children":1824},{"className":1823},[],[1825],{"type":49,"value":1826},"src\u002Fresolvers\u002Findex.js",{"type":49,"value":1828},", handler is ",{"type":43,"tag":108,"props":1830,"children":1832},{"className":1831},[],[1833],{"type":49,"value":1834},"resolvers\u002Findex.handler",{"type":49,"value":1836}," (not ",{"type":43,"tag":108,"props":1838,"children":1840},{"className":1839},[],[1841],{"type":49,"value":1842},"index.handler",{"type":49,"value":1844}," or ",{"type":43,"tag":108,"props":1846,"children":1848},{"className":1847},[],[1849],{"type":49,"value":1850},"src\u002Fresolvers\u002Findex.handler",{"type":49,"value":1852},"). See Handler Path Resolution below",{"type":43,"tag":352,"props":1854,"children":1855},{},[1856,1867,1886],{"type":43,"tag":374,"props":1857,"children":1858},{},[1859,1865],{"type":43,"tag":108,"props":1860,"children":1862},{"className":1861},[],[1863],{"type":49,"value":1864},"invoke()",{"type":49,"value":1866}," returns undefined, no errors in logs",{"type":43,"tag":374,"props":1868,"children":1869},{},[1870,1872,1878,1880],{"type":49,"value":1871},"Frontend ",{"type":43,"tag":108,"props":1873,"children":1875},{"className":1874},[],[1876],{"type":49,"value":1877},"invoke('name')",{"type":49,"value":1879}," doesn't match ",{"type":43,"tag":108,"props":1881,"children":1883},{"className":1882},[],[1884],{"type":49,"value":1885},"resolver.define('name')",{"type":43,"tag":374,"props":1887,"children":1888},{},[1889],{"type":49,"value":1890},"The invoke name must exactly match the resolver.define name. Check both files — this is a different check than function key in manifest",{"type":43,"tag":352,"props":1892,"children":1893},{},[1894,1913,1930],{"type":43,"tag":374,"props":1895,"children":1896},{},[1897,1903,1905,1911],{"type":43,"tag":108,"props":1898,"children":1900},{"className":1899},[],[1901],{"type":49,"value":1902},"Module not found",{"type":49,"value":1904}," \u002F doubled path like ",{"type":43,"tag":108,"props":1906,"children":1908},{"className":1907},[],[1909],{"type":49,"value":1910},"src\u002Fsrc\u002F...",{"type":49,"value":1912}," on deploy",{"type":43,"tag":374,"props":1914,"children":1915},{},[1916,1918,1923,1925],{"type":49,"value":1917},"Handler path includes ",{"type":43,"tag":108,"props":1919,"children":1921},{"className":1920},[],[1922],{"type":49,"value":1818},{"type":49,"value":1924}," prefix, but bundler already resolves from ",{"type":43,"tag":108,"props":1926,"children":1928},{"className":1927},[],[1929],{"type":49,"value":1818},{"type":43,"tag":374,"props":1931,"children":1932},{},[1933,1935,1940,1942,1947,1949],{"type":49,"value":1934},"Remove ",{"type":43,"tag":108,"props":1936,"children":1938},{"className":1937},[],[1939],{"type":49,"value":1818},{"type":49,"value":1941}," prefix from handler path. Use ",{"type":43,"tag":108,"props":1943,"children":1945},{"className":1944},[],[1946],{"type":49,"value":1834},{"type":49,"value":1948}," not ",{"type":43,"tag":108,"props":1950,"children":1952},{"className":1951},[],[1953],{"type":49,"value":1850},{"type":43,"tag":352,"props":1955,"children":1956},{},[1957,1968,1973],{"type":43,"tag":374,"props":1958,"children":1959},{},[1960,1966],{"type":43,"tag":108,"props":1961,"children":1963},{"className":1962},[],[1964],{"type":49,"value":1965},"npm install -g",{"type":49,"value":1967}," permission error \u002F cannot install forge globally",{"type":43,"tag":374,"props":1969,"children":1970},{},[1971],{"type":49,"value":1972},"No sudo or write access to global npm directory",{"type":43,"tag":374,"props":1974,"children":1975},{},[1976,1978,1983,1985,1990],{"type":49,"value":1977},"Use ",{"type":43,"tag":108,"props":1979,"children":1981},{"className":1980},[],[1982],{"type":49,"value":307},{"type":49,"value":1984}," as a drop-in replacement for all ",{"type":43,"tag":108,"props":1986,"children":1988},{"className":1987},[],[1989],{"type":49,"value":172},{"type":49,"value":1991}," commands (lint, deploy, logs, install). No global install needed",{"type":43,"tag":58,"props":1993,"children":1995},{"id":1994},"handler-path-resolution",[1996],{"type":49,"value":1997},"Handler Path Resolution",{"type":43,"tag":52,"props":1999,"children":2000},{},[2001,2003,2009,2011,2016,2018,2024],{"type":49,"value":2002},"The ",{"type":43,"tag":108,"props":2004,"children":2006},{"className":2005},[],[2007],{"type":49,"value":2008},"handler",{"type":49,"value":2010}," field in ",{"type":43,"tag":108,"props":2012,"children":2014},{"className":2013},[],[2015],{"type":49,"value":1534},{"type":49,"value":2017}," has the format ",{"type":43,"tag":108,"props":2019,"children":2021},{"className":2020},[],[2022],{"type":49,"value":2023},"\u003Cpath>.\u003Cexport>",{"type":49,"value":2025},", where:",{"type":43,"tag":78,"props":2027,"children":2028},{},[2029,2059],{"type":43,"tag":82,"props":2030,"children":2031},{},[2032,2038,2040,2050,2052,2057],{"type":43,"tag":108,"props":2033,"children":2035},{"className":2034},[],[2036],{"type":49,"value":2037},"\u003Cpath>",{"type":49,"value":2039}," is the file path ",{"type":43,"tag":70,"props":2041,"children":2042},{},[2043,2045],{"type":49,"value":2044},"relative to ",{"type":43,"tag":108,"props":2046,"children":2048},{"className":2047},[],[2049],{"type":49,"value":1818},{"type":49,"value":2051}," (without ",{"type":43,"tag":108,"props":2053,"children":2055},{"className":2054},[],[2056],{"type":49,"value":1818},{"type":49,"value":2058}," prefix, without file extension)",{"type":43,"tag":82,"props":2060,"children":2061},{},[2062,2068],{"type":43,"tag":108,"props":2063,"children":2065},{"className":2064},[],[2066],{"type":49,"value":2067},"\u003Cexport>",{"type":49,"value":2069}," is the named export from that file",{"type":43,"tag":52,"props":2071,"children":2072},{},[2073],{"type":43,"tag":70,"props":2074,"children":2075},{},[2076],{"type":49,"value":2077},"Examples:",{"type":43,"tag":344,"props":2079,"children":2080},{},[2081,2102],{"type":43,"tag":348,"props":2082,"children":2083},{},[2084],{"type":43,"tag":352,"props":2085,"children":2086},{},[2087,2092,2097],{"type":43,"tag":356,"props":2088,"children":2089},{},[2090],{"type":49,"value":2091},"Resolver file location",{"type":43,"tag":356,"props":2093,"children":2094},{},[2095],{"type":49,"value":2096},"Export in file",{"type":43,"tag":356,"props":2098,"children":2099},{},[2100],{"type":49,"value":2101},"Correct handler value",{"type":43,"tag":367,"props":2103,"children":2104},{},[2105,2133,2161],{"type":43,"tag":352,"props":2106,"children":2107},{},[2108,2116,2125],{"type":43,"tag":374,"props":2109,"children":2110},{},[2111],{"type":43,"tag":108,"props":2112,"children":2114},{"className":2113},[],[2115],{"type":49,"value":1826},{"type":43,"tag":374,"props":2117,"children":2118},{},[2119],{"type":43,"tag":108,"props":2120,"children":2122},{"className":2121},[],[2123],{"type":49,"value":2124},"export const handler = ...",{"type":43,"tag":374,"props":2126,"children":2127},{},[2128],{"type":43,"tag":108,"props":2129,"children":2131},{"className":2130},[],[2132],{"type":49,"value":1834},{"type":43,"tag":352,"props":2134,"children":2135},{},[2136,2145,2153],{"type":43,"tag":374,"props":2137,"children":2138},{},[2139],{"type":43,"tag":108,"props":2140,"children":2142},{"className":2141},[],[2143],{"type":49,"value":2144},"src\u002Findex.js",{"type":43,"tag":374,"props":2146,"children":2147},{},[2148],{"type":43,"tag":108,"props":2149,"children":2151},{"className":2150},[],[2152],{"type":49,"value":2124},{"type":43,"tag":374,"props":2154,"children":2155},{},[2156],{"type":43,"tag":108,"props":2157,"children":2159},{"className":2158},[],[2160],{"type":49,"value":1842},{"type":43,"tag":352,"props":2162,"children":2163},{},[2164,2173,2182],{"type":43,"tag":374,"props":2165,"children":2166},{},[2167],{"type":43,"tag":108,"props":2168,"children":2170},{"className":2169},[],[2171],{"type":49,"value":2172},"src\u002Fbackend\u002Fresolver.ts",{"type":43,"tag":374,"props":2174,"children":2175},{},[2176],{"type":43,"tag":108,"props":2177,"children":2179},{"className":2178},[],[2180],{"type":49,"value":2181},"export const run = ...",{"type":43,"tag":374,"props":2183,"children":2184},{},[2185],{"type":43,"tag":108,"props":2186,"children":2188},{"className":2187},[],[2189],{"type":49,"value":2190},"backend\u002Fresolver.run",{"type":43,"tag":52,"props":2192,"children":2193},{},[2194],{"type":43,"tag":70,"props":2195,"children":2196},{},[2197],{"type":49,"value":2198},"Common mistakes:",{"type":43,"tag":78,"props":2200,"children":2201},{},[2202,2218,2241],{"type":43,"tag":82,"props":2203,"children":2204},{},[2205,2210,2212],{"type":43,"tag":108,"props":2206,"children":2208},{"className":2207},[],[2209],{"type":49,"value":1842},{"type":49,"value":2211}," — wrong if the file is in a subdirectory like ",{"type":43,"tag":108,"props":2213,"children":2215},{"className":2214},[],[2216],{"type":49,"value":2217},"src\u002Fresolvers\u002F",{"type":43,"tag":82,"props":2219,"children":2220},{},[2221,2226,2228,2233,2235],{"type":43,"tag":108,"props":2222,"children":2224},{"className":2223},[],[2225],{"type":49,"value":1850},{"type":49,"value":2227}," — wrong: bundler prefixes ",{"type":43,"tag":108,"props":2229,"children":2231},{"className":2230},[],[2232],{"type":49,"value":1818},{"type":49,"value":2234}," automatically, resulting in ",{"type":43,"tag":108,"props":2236,"children":2238},{"className":2237},[],[2239],{"type":49,"value":2240},"src\u002Fsrc\u002Fresolvers\u002F...",{"type":43,"tag":82,"props":2242,"children":2243},{},[2244,2250,2252,2257,2258],{"type":43,"tag":108,"props":2245,"children":2247},{"className":2246},[],[2248],{"type":49,"value":2249},"resolvers\u002Findex.run",{"type":49,"value":2251}," — wrong if the file exports ",{"type":43,"tag":108,"props":2253,"children":2255},{"className":2254},[],[2256],{"type":49,"value":2008},{"type":49,"value":1948},{"type":43,"tag":108,"props":2259,"children":2261},{"className":2260},[],[2262],{"type":49,"value":2263},"run",{"type":43,"tag":52,"props":2265,"children":2266},{},[2267,2272,2274,2279,2281,2287],{"type":43,"tag":70,"props":2268,"children":2269},{},[2270],{"type":49,"value":2271},"Diagnostic trick:",{"type":49,"value":2273}," If ",{"type":43,"tag":108,"props":2275,"children":2277},{"className":2276},[],[2278],{"type":49,"value":113},{"type":49,"value":2280}," reports \"cannot find associated file\" but you're sure the file exists, try ",{"type":43,"tag":108,"props":2282,"children":2284},{"className":2283},[],[2285],{"type":49,"value":2286},"forge deploy --no-verify",{"type":49,"value":2288},". The bundler error message shows the fully resolved path, which reveals whether the path is being doubled or misresolved.",{"type":43,"tag":58,"props":2290,"children":2292},{"id":2291},"invoke-name-vs-function-key",[2293],{"type":49,"value":2294},"Invoke Name vs Function Key",{"type":43,"tag":52,"props":2296,"children":2297},{},[2298,2300,2305],{"type":49,"value":2299},"There are ",{"type":43,"tag":70,"props":2301,"children":2302},{},[2303],{"type":49,"value":2304},"two separate name-matching requirements",{"type":49,"value":2306}," for UI Kit resolvers:",{"type":43,"tag":1323,"props":2308,"children":2309},{},[2310,2333],{"type":43,"tag":82,"props":2311,"children":2312},{},[2313,2323,2325,2331],{"type":43,"tag":70,"props":2314,"children":2315},{},[2316,2318],{"type":49,"value":2317},"manifest.yml ",{"type":43,"tag":108,"props":2319,"children":2321},{"className":2320},[],[2322],{"type":49,"value":1541},{"type":49,"value":2324}," must match the ",{"type":43,"tag":108,"props":2326,"children":2328},{"className":2327},[],[2329],{"type":49,"value":2330},"resolver: function:",{"type":49,"value":2332}," reference in the module definition",{"type":43,"tag":82,"props":2334,"children":2335},{},[2336,2345,2347,2356],{"type":43,"tag":70,"props":2337,"children":2338},{},[2339,2340],{"type":49,"value":1871},{"type":43,"tag":108,"props":2341,"children":2343},{"className":2342},[],[2344],{"type":49,"value":1877},{"type":49,"value":2346}," must exactly match ",{"type":43,"tag":70,"props":2348,"children":2349},{},[2350],{"type":43,"tag":108,"props":2351,"children":2353},{"className":2352},[],[2354],{"type":49,"value":2355},"resolver.define('name', ...)",{"type":49,"value":2357}," in the backend",{"type":43,"tag":52,"props":2359,"children":2360},{},[2361,2363,2368],{"type":49,"value":2362},"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 ",{"type":43,"tag":70,"props":2364,"children":2365},{},[2366],{"type":49,"value":2367},"both",{"type":49,"value":2369}," matching relationships.",{"type":43,"tag":58,"props":2371,"children":2373},{"id":2372},"api-migration-v1-v2",[2374],{"type":49,"value":2375},"API Migration (v1 → v2)",{"type":43,"tag":52,"props":2377,"children":2378},{},[2379,2381,2386],{"type":49,"value":2380},"Atlassian is progressively deprecating v1 REST API endpoints. When you see a ",{"type":43,"tag":70,"props":2382,"children":2383},{},[2384],{"type":49,"value":2385},"410 Gone",{"type":49,"value":2387}," response:",{"type":43,"tag":1323,"props":2389,"children":2390},{},[2391,2402,2472,2513,2539],{"type":43,"tag":82,"props":2392,"children":2393},{},[2394,2395,2400],{"type":49,"value":1528},{"type":43,"tag":108,"props":2396,"children":2398},{"className":2397},[],[2399],{"type":49,"value":1068},{"type":49,"value":2401}," for the exact error — it will show which endpoint returned 410",{"type":43,"tag":82,"props":2403,"children":2404},{},[2405,2407],{"type":49,"value":2406},"Identify the v2 equivalent:\n",{"type":43,"tag":78,"props":2408,"children":2409},{},[2410,2450],{"type":43,"tag":82,"props":2411,"children":2412},{},[2413,2418,2420,2426,2428,2434,2436,2442,2443,2449],{"type":43,"tag":70,"props":2414,"children":2415},{},[2416],{"type":49,"value":2417},"URL pattern",{"type":49,"value":2419},": ",{"type":43,"tag":108,"props":2421,"children":2423},{"className":2422},[],[2424],{"type":49,"value":2425},"\u002Fwiki\u002Frest\u002Fapi\u002Fcontent\u002F...",{"type":49,"value":2427}," → ",{"type":43,"tag":108,"props":2429,"children":2431},{"className":2430},[],[2432],{"type":49,"value":2433},"\u002Fwiki\u002Fapi\u002Fv2\u002Fpages\u002F...",{"type":49,"value":2435}," (or ",{"type":43,"tag":108,"props":2437,"children":2439},{"className":2438},[],[2440],{"type":49,"value":2441},"\u002Fblogposts\u002F...",{"type":49,"value":148},{"type":43,"tag":108,"props":2444,"children":2446},{"className":2445},[],[2447],{"type":49,"value":2448},"\u002Fspaces\u002F...",{"type":49,"value":1158},{"type":43,"tag":82,"props":2451,"children":2452},{},[2453,2458,2459,2465,2466],{"type":43,"tag":70,"props":2454,"children":2455},{},[2456],{"type":49,"value":2457},"Jira",{"type":49,"value":2419},{"type":43,"tag":108,"props":2460,"children":2462},{"className":2461},[],[2463],{"type":49,"value":2464},"\u002Frest\u002Fapi\u002F2\u002F...",{"type":49,"value":2427},{"type":43,"tag":108,"props":2467,"children":2469},{"className":2468},[],[2470],{"type":49,"value":2471},"\u002Frest\u002Fapi\u002F3\u002F...",{"type":43,"tag":82,"props":2473,"children":2474},{},[2475,2477,2482,2484,2489,2491,2497,2499,2505,2507],{"type":49,"value":2476},"Update ",{"type":43,"tag":70,"props":2478,"children":2479},{},[2480],{"type":49,"value":2481},"pagination",{"type":49,"value":2483},": v2 Confluence APIs use ",{"type":43,"tag":70,"props":2485,"children":2486},{},[2487],{"type":49,"value":2488},"cursor-based",{"type":49,"value":2490}," pagination (",{"type":43,"tag":108,"props":2492,"children":2494},{"className":2493},[],[2495],{"type":49,"value":2496},"cursor",{"type":49,"value":2498}," parameter) instead of offset-based (",{"type":43,"tag":108,"props":2500,"children":2502},{"className":2501},[],[2503],{"type":49,"value":2504},"start",{"type":49,"value":2506}," parameter). The next cursor is in ",{"type":43,"tag":108,"props":2508,"children":2510},{"className":2509},[],[2511],{"type":49,"value":2512},"data._links.next",{"type":43,"tag":82,"props":2514,"children":2515},{},[2516,2517,2522,2524,2530,2532,2538],{"type":49,"value":2476},{"type":43,"tag":70,"props":2518,"children":2519},{},[2520],{"type":49,"value":2521},"response shape",{"type":49,"value":2523},": v2 may return different field names (e.g. ",{"type":43,"tag":108,"props":2525,"children":2527},{"className":2526},[],[2528],{"type":49,"value":2529},"authorId",{"type":49,"value":2531}," instead of nested ",{"type":43,"tag":108,"props":2533,"children":2535},{"className":2534},[],[2536],{"type":49,"value":2537},"by.accountId",{"type":49,"value":1158},{"type":43,"tag":82,"props":2540,"children":2541},{},[2542],{"type":49,"value":2543},"Redeploy and check logs to confirm the fix",{"type":43,"tag":52,"props":2545,"children":2546},{},[2547,2552],{"type":43,"tag":70,"props":2548,"children":2549},{},[2550],{"type":49,"value":2551},"Do NOT",{"type":49,"value":2553}," treat 410 as a permissions issue — it means the endpoint no longer exists, not that access is denied.",{"type":43,"tag":58,"props":2555,"children":2557},{"id":2556},"step-8-cleanup",[2558],{"type":49,"value":2559},"Step 8: Cleanup",{"type":43,"tag":52,"props":2561,"children":2562},{},[2563],{"type":49,"value":2564},"Once the issue is resolved:",{"type":43,"tag":1323,"props":2566,"children":2567},{},[2568,2581,2586,2597,2627],{"type":43,"tag":82,"props":2569,"children":2570},{},[2571,2573,2579],{"type":49,"value":2572},"Remove any ",{"type":43,"tag":108,"props":2574,"children":2576},{"className":2575},[],[2577],{"type":49,"value":2578},"console.error('[DEBUG] ...')",{"type":49,"value":2580}," statements you added.",{"type":43,"tag":82,"props":2582,"children":2583},{},[2584],{"type":49,"value":2585},"Remove verbose flags from any scripts.",{"type":43,"tag":82,"props":2587,"children":2588},{},[2589,2590,2595],{"type":49,"value":1603},{"type":43,"tag":108,"props":2591,"children":2593},{"className":2592},[],[2594],{"type":49,"value":113},{"type":49,"value":2596}," one final time to confirm clean state.",{"type":43,"tag":82,"props":2598,"children":2599},{},[2600,2602],{"type":49,"value":2601},"Redeploy if you modified code during debugging:\n",{"type":43,"tag":514,"props":2603,"children":2604},{"className":516,"code":763,"language":518,"meta":519,"style":519},[2605],{"type":43,"tag":108,"props":2606,"children":2607},{"__ignoreMap":519},[2608],{"type":43,"tag":525,"props":2609,"children":2610},{"class":527,"line":528},[2611,2615,2619,2623],{"type":43,"tag":525,"props":2612,"children":2613},{"style":532},[2614],{"type":49,"value":172},{"type":43,"tag":525,"props":2616,"children":2617},{"style":537},[2618],{"type":49,"value":779},{"type":43,"tag":525,"props":2620,"children":2621},{"style":537},[2622],{"type":49,"value":784},{"type":43,"tag":525,"props":2624,"children":2625},{"style":537},[2626],{"type":49,"value":789},{"type":43,"tag":82,"props":2628,"children":2629},{},[2630,2632,2637],{"type":49,"value":2631},"Confirm the fix works by triggering the app and checking that ",{"type":43,"tag":108,"props":2633,"children":2635},{"className":2634},[],[2636],{"type":49,"value":1068},{"type":49,"value":2638}," shows no new errors.",{"type":43,"tag":58,"props":2640,"children":2642},{"id":2641},"escalation",[2643],{"type":49,"value":2644},"Escalation",{"type":43,"tag":52,"props":2646,"children":2647},{},[2648],{"type":49,"value":2649},"If none of the above resolves the issue:",{"type":43,"tag":78,"props":2651,"children":2652},{},[2653,2665,2676],{"type":43,"tag":82,"props":2654,"children":2655},{},[2656,2657,2663],{"type":49,"value":1603},{"type":43,"tag":108,"props":2658,"children":2660},{"className":2659},[],[2661],{"type":49,"value":2662},"forge logs -e development --verbose --limit 200",{"type":49,"value":2664}," for extended output.",{"type":43,"tag":82,"props":2666,"children":2667},{},[2668,2670],{"type":49,"value":2669},"Check the Forge changelog for known issues: ",{"type":43,"tag":108,"props":2671,"children":2673},{"className":2672},[],[2674],{"type":49,"value":2675},"search-forge-docs \"known issues \u003Cerror-text>\"",{"type":43,"tag":82,"props":2677,"children":2678},{},[2679,2681,2687],{"type":49,"value":2680},"If the error is in a Forge platform API (not your code), note the ",{"type":43,"tag":108,"props":2682,"children":2684},{"className":2683},[],[2685],{"type":49,"value":2686},"traceId",{"type":49,"value":2688}," from the log output — this is what Atlassian support needs.",{"type":43,"tag":58,"props":2690,"children":2692},{"id":2691},"authentication-errors",[2693],{"type":49,"value":2694},"Authentication Errors",{"type":43,"tag":52,"props":2696,"children":2697},{},[2698],{"type":49,"value":2699},"If any command fails with \"not authenticated\" or \"run forge login\":",{"type":43,"tag":1323,"props":2701,"children":2702},{},[2703,2719,2738,2762],{"type":43,"tag":82,"props":2704,"children":2705},{},[2706,2708],{"type":49,"value":2707},"Tell the user to create an API token at ",{"type":43,"tag":70,"props":2709,"children":2710},{},[2711],{"type":43,"tag":2712,"props":2713,"children":2717},"a",{"href":2714,"rel":2715},"https:\u002F\u002Fid.atlassian.com\u002Fmanage\u002Fapi-tokens",[2716],"nofollow",[2718],{"type":49,"value":2714},{"type":43,"tag":82,"props":2720,"children":2721},{},[2722,2724,2729,2731,2736],{"type":49,"value":2723},"Tell them to run ",{"type":43,"tag":108,"props":2725,"children":2727},{"className":2726},[],[2728],{"type":49,"value":146},{"type":49,"value":2730}," in ",{"type":43,"tag":70,"props":2732,"children":2733},{},[2734],{"type":49,"value":2735},"their own terminal",{"type":49,"value":2737}," (not via the agent) — it will prompt for their email and the API token",{"type":43,"tag":82,"props":2739,"children":2740},{},[2741,2743],{"type":49,"value":2742},"Example message: ",{"type":43,"tag":124,"props":2744,"children":2745},{},[2746,2748,2753,2755,2760],{"type":49,"value":2747},"\"You need to log in. Create an API token at ",{"type":43,"tag":2712,"props":2749,"children":2751},{"href":2714,"rel":2750},[2716],[2752],{"type":49,"value":2714},{"type":49,"value":2754},", then run ",{"type":43,"tag":108,"props":2756,"children":2758},{"className":2757},[],[2759],{"type":49,"value":146},{"type":49,"value":2761}," in your terminal. Enter your Atlassian email and the token when prompted — do not paste the token here.\"",{"type":43,"tag":82,"props":2763,"children":2764},{},[2765],{"type":49,"value":2766},"After they confirm login, resume debugging from where you left off.",{"type":43,"tag":58,"props":2768,"children":2770},{"id":2769},"token-efficiency-rules",[2771],{"type":49,"value":2772},"Token Efficiency Rules",{"type":43,"tag":52,"props":2774,"children":2775},{},[2776],{"type":49,"value":2777},"Follow these to keep context usage low:",{"type":43,"tag":78,"props":2779,"children":2780},{},[2781,2793,2947,2959,2964,2975,2987],{"type":43,"tag":82,"props":2782,"children":2783},{},[2784,2786,2791],{"type":49,"value":2785},"Read ",{"type":43,"tag":108,"props":2787,"children":2789},{"className":2788},[],[2790],{"type":49,"value":1068},{"type":49,"value":2792}," before reading any source file — logs usually reveal the root cause without needing to inspect code.",{"type":43,"tag":82,"props":2794,"children":2795},{},[2796,2798],{"type":49,"value":2797},"Read only the specific file implicated by the error. Match the error to its file:\n",{"type":43,"tag":78,"props":2799,"children":2800},{},[2801,2820,2846,2872,2888,2898,2923],{"type":43,"tag":82,"props":2802,"children":2803},{},[2804,2810,2812,2818],{"type":43,"tag":108,"props":2805,"children":2807},{"className":2806},[],[2808],{"type":49,"value":2809},"npm ERR! missing script: build",{"type":49,"value":2811}," → check only ",{"type":43,"tag":108,"props":2813,"children":2815},{"className":2814},[],[2816],{"type":49,"value":2817},"package.json",{"type":49,"value":2819}," (scripts section)",{"type":43,"tag":82,"props":2821,"children":2822},{},[2823,2829,2831,2837,2839,2844],{"type":43,"tag":108,"props":2824,"children":2826},{"className":2825},[],[2827],{"type":49,"value":2828},"invalid manifest",{"type":49,"value":2830}," \u002F ",{"type":43,"tag":108,"props":2832,"children":2834},{"className":2833},[],[2835],{"type":49,"value":2836},"unexpected key",{"type":49,"value":2838}," → run ",{"type":43,"tag":108,"props":2840,"children":2842},{"className":2841},[],[2843],{"type":49,"value":113},{"type":49,"value":2845}," first, then only the specific manifest field",{"type":43,"tag":82,"props":2847,"children":2848},{},[2849,2855,2857,2862,2864,2870],{"type":43,"tag":108,"props":2850,"children":2852},{"className":2851},[],[2853],{"type":49,"value":2854},"Resolver not found",{"type":49,"value":2856}," → check only the function key in ",{"type":43,"tag":108,"props":2858,"children":2860},{"className":2859},[],[2861],{"type":49,"value":1534},{"type":49,"value":2863}," vs ",{"type":43,"tag":108,"props":2865,"children":2867},{"className":2866},[],[2868],{"type":49,"value":2869},"resolver.define()",{"type":49,"value":2871}," in the resolver file",{"type":43,"tag":82,"props":2873,"children":2874},{},[2875,2881,2883],{"type":43,"tag":108,"props":2876,"children":2878},{"className":2877},[],[2879],{"type":49,"value":2880},"403 \u002F permission denied",{"type":49,"value":2882}," → check only the scopes in ",{"type":43,"tag":108,"props":2884,"children":2886},{"className":2885},[],[2887],{"type":49,"value":1534},{"type":43,"tag":82,"props":2889,"children":2890},{},[2891,2896],{"type":43,"tag":108,"props":2892,"children":2894},{"className":2893},[],[2895],{"type":49,"value":2385},{"type":49,"value":2897}," → check the API endpoint URL in the resolver file; don't check scopes or manifest",{"type":43,"tag":82,"props":2899,"children":2900},{},[2901,2906,2908,2913,2915,2921],{"type":43,"tag":108,"props":2902,"children":2904},{"className":2903},[],[2905],{"type":49,"value":1800},{"type":49,"value":2907}," → check the handler path in ",{"type":43,"tag":108,"props":2909,"children":2911},{"className":2910},[],[2912],{"type":49,"value":1534},{"type":49,"value":2914}," and the file location; use ",{"type":43,"tag":108,"props":2916,"children":2918},{"className":2917},[],[2919],{"type":49,"value":2920},"--no-verify",{"type":49,"value":2922}," to see the bundler's resolved path",{"type":43,"tag":82,"props":2924,"children":2925},{},[2926,2931,2933,2938,2940,2945],{"type":43,"tag":108,"props":2927,"children":2929},{"className":2928},[],[2930],{"type":49,"value":1864},{"type":49,"value":2932}," returns undefined → check both the frontend ",{"type":43,"tag":108,"props":2934,"children":2936},{"className":2935},[],[2937],{"type":49,"value":1877},{"type":49,"value":2939}," AND backend ",{"type":43,"tag":108,"props":2941,"children":2943},{"className":2942},[],[2944],{"type":49,"value":1885},{"type":49,"value":2946}," — two files, but targeted reads",{"type":43,"tag":82,"props":2948,"children":2949},{},[2950,2952,2957],{"type":49,"value":2951},"Don't read ",{"type":43,"tag":108,"props":2953,"children":2955},{"className":2954},[],[2956],{"type":49,"value":1534},{"type":49,"value":2958}," for npm\u002Fbuild errors — they are unrelated.",{"type":43,"tag":82,"props":2960,"children":2961},{},[2962],{"type":49,"value":2963},"Don't re-read a file you've already read in this session unless it changed.",{"type":43,"tag":82,"props":2965,"children":2966},{},[2967,2969,2973],{"type":49,"value":2968},"Stop the diagnostic chain the moment you find a match in the Common Error Patterns table. ",{"type":43,"tag":70,"props":2970,"children":2971},{},[2972],{"type":49,"value":262},{"type":49,"value":2974},": when multiple independent bugs exist (e.g. deploy error + runtime error), fix the first, deploy, then check for the next.",{"type":43,"tag":82,"props":2976,"children":2977},{},[2978,2980,2985],{"type":49,"value":2979},"Don't run ",{"type":43,"tag":108,"props":2981,"children":2983},{"className":2982},[],[2984],{"type":49,"value":382},{"type":49,"value":2986}," more than once per fix attempt without a clear reason.",{"type":43,"tag":82,"props":2988,"children":2989},{},[2990,2991,2996,2998,3003,3005,3010],{"type":49,"value":1977},{"type":43,"tag":108,"props":2992,"children":2994},{"className":2993},[],[2995],{"type":49,"value":2286},{"type":49,"value":2997}," as a ",{"type":43,"tag":70,"props":2999,"children":3000},{},[3001],{"type":49,"value":3002},"diagnostic step",{"type":49,"value":3004}," 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 ",{"type":43,"tag":108,"props":3006,"children":3008},{"className":3007},[],[3009],{"type":49,"value":2920},{"type":49,"value":935},{"type":43,"tag":3012,"props":3013,"children":3014},"style",{},[3015],{"type":49,"value":3016},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":3018,"total":1283},[3019,3034,3049,3065,3079,3085],{"slug":3020,"name":3020,"fn":3021,"description":3022,"org":3023,"tags":3024,"stars":20,"repoUrl":21,"updatedAt":3033},"forge-app-builder","build and deploy Atlassian Forge apps","Guides building, deploying, troubleshooting, and installing Atlassian Forge apps — custom extensions built with the Forge CLI (forge create, forge deploy, forge install). Use when the user wants to create a Forge app (issue panels, dashboard gadgets, Confluence macros, global pages), is encountering Forge CLI errors or deployment issues (e.g. forge install failures, environment errors), or needs help with Forge-specific concepts like resolvers, UI Kit, manifest scopes, or developer spaces. Do not use for general Jira configuration, automation rules, JQL queries, or Atlassian REST API usage outside of a Forge app context.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3025,3026,3029,3030],{"name":9,"slug":8,"type":15},{"name":3027,"slug":3028,"type":15},"CLI","cli",{"name":13,"slug":14,"type":15},{"name":3031,"slug":3032,"type":15},"Plugin Development","plugin-development","2026-07-12T07:58:52.007851",{"slug":3035,"name":3035,"fn":3036,"description":3037,"org":3038,"tags":3039,"stars":20,"repoUrl":21,"updatedAt":3048},"forge-app-review","review Atlassian Forge app readiness","Performs a lightweight pre-release readiness review of Atlassian Forge apps across manifest\u002Fmodule wiring, architecture, runtime compatibility, dependency posture, tests, deploy readiness, and obvious security, cost, or reliability smells. Use when the user asks \"review my Forge app\", \"pre-deploy check\", \"is this app ready to ship\", \"review manifest\", \"general app review\", \"release readiness\", or asks for a broad quality pass. Do not use for deep security audits\u002FSAST\u002Fexploitability review, cost optimization, or diagnosing a known broken app; route those to forge-security-review, forge-cost-optimizer, or forge-debugger respectively.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3040,3041,3044,3045],{"name":9,"slug":8,"type":15},{"name":3042,"slug":3043,"type":15},"Code Analysis","code-analysis",{"name":13,"slug":14,"type":15},{"name":3046,"slug":3047,"type":15},"QA","qa","2026-07-12T07:58:50.744672",{"slug":3050,"name":3050,"fn":3051,"description":3052,"org":3053,"tags":3054,"stars":20,"repoUrl":21,"updatedAt":3064},"forge-connector","build Atlassian Forge Teamwork Graph connectors","Guides building and deploying Atlassian Forge Teamwork Graph connector apps that ingest external data into Atlassian's Teamwork Graph, making it searchable in Rovo Search and surfaced in Rovo Chat. Use when the user wants to build a Forge connector, ingest external data into Atlassian, connect a third-party tool (e.g. Google Drive, ServiceNow, Salesforce) to Atlassian, make external content searchable in Rovo, build a graph:connector module, use the @forge\u002Fteamwork-graph SDK, or implement onConnectionChange \u002F validateConnection functions.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3055,3058,3061],{"name":3056,"slug":3057,"type":15},"API Development","api-development",{"name":3059,"slug":3060,"type":15},"Engineering","engineering",{"name":3062,"slug":3063,"type":15},"Enterprise Search","enterprise-search","2026-07-12T07:58:48.520248",{"slug":3066,"name":3066,"fn":3067,"description":3068,"org":3069,"tags":3070,"stars":20,"repoUrl":21,"updatedAt":3078},"forge-cost-optimizer","optimize Atlassian Forge platform costs","Optimizes Atlassian Forge apps to reduce platform consumption and avoid unnecessary costs using Atlassian's \"Optimise Forge platform costs\" guidance. Use when the user asks to optimize Forge app costs, reduce Forge invocations, lower GB-seconds, reduce storage or log usage, tune memory, replace polling, improve scheduled triggers, reduce KVS writes, move work to the frontend, use bridge APIs, batch API calls, add caching, or evaluate Forge Remote trade-offs. By default, perform an audit first and offer to make the recommended changes after presenting the audit. Only modify files immediately when the user explicitly asks the agent to implement or apply optimizations.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3071,3072,3075],{"name":9,"slug":8,"type":15},{"name":3073,"slug":3074,"type":15},"Cost Optimization","cost-optimization",{"name":3076,"slug":3077,"type":15},"Operations","operations","2026-07-12T07:58:53.557299",{"slug":4,"name":4,"fn":5,"description":6,"org":3080,"tags":3081,"stars":20,"repoUrl":21,"updatedAt":22},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3082,3083,3084],{"name":9,"slug":8,"type":15},{"name":18,"slug":19,"type":15},{"name":13,"slug":14,"type":15},{"slug":3086,"name":3086,"fn":3087,"description":3088,"org":3089,"tags":3090,"stars":20,"repoUrl":21,"updatedAt":3098},"forge-security-review","perform security reviews for Forge apps","Performs a white-box security review of Atlassian Forge apps using structured, Forge-specific security rules and evidence-driven reporting. Use when the user asks for a Forge security review, security audit, vuln assessment, pentest-style code review, authz review, tenant isolation analysis, web trigger hardening, or static analysis execution for a Forge app.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3091,3094,3095],{"name":3092,"slug":3093,"type":15},"Audit","audit",{"name":3042,"slug":3043,"type":15},{"name":3096,"slug":3097,"type":15},"Security","security","2026-07-12T07:58:54.806538",{"items":3100,"total":3231},[3101,3121,3139,3156,3169,3180,3193,3200,3207,3213,3219,3225],{"slug":3102,"name":3102,"fn":3103,"description":3104,"org":3105,"tags":3106,"stars":3118,"repoUrl":3119,"updatedAt":3120},"capture-tasks-from-meeting-notes","create Jira tasks from meeting notes","Analyze meeting notes to find action items and create Jira tasks for assigned work. When an agent needs to: (1) Create Jira tasks or tickets from meeting notes, (2) Extract or find action items from notes or Confluence pages, (3) Parse meeting notes for assigned tasks, or (4) Analyze notes and generate tasks for team members. Identifies assignees, looks up account IDs, and creates tasks with proper context.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3107,3110,3112,3115],{"name":3108,"slug":3109,"type":15},"Automation","automation",{"name":2457,"slug":3111,"type":15},"jira",{"name":3113,"slug":3114,"type":15},"Meetings","meetings",{"name":3116,"slug":3117,"type":15},"Task Management","task-management",848,"https:\u002F\u002Fgithub.com\u002Fatlassian\u002Fatlassian-mcp-server","2026-07-12T07:58:45.323861",{"slug":3122,"name":3122,"fn":3123,"description":3124,"org":3125,"tags":3126,"stars":3118,"repoUrl":3119,"updatedAt":3138},"generate-status-report","generate project status reports for Confluence","Generate project status reports from Jira issues and publish to Confluence. When an agent needs to: (1) Create a status report for a project, (2) Summarize project progress or updates, (3) Generate weekly\u002Fdaily reports from Jira, (4) Publish status summaries to Confluence, or (5) Analyze project blockers and completion. Queries Jira issues, categorizes by status\u002Fpriority, and creates formatted reports for delivery managers and executives.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3127,3128,3131,3132,3135],{"name":9,"slug":8,"type":15},{"name":3129,"slug":3130,"type":15},"Confluence","confluence",{"name":2457,"slug":3111,"type":15},{"name":3133,"slug":3134,"type":15},"Project Management","project-management",{"name":3136,"slug":3137,"type":15},"Reporting","reporting","2026-07-12T07:58:38.457696",{"slug":3140,"name":3140,"fn":3141,"description":3142,"org":3143,"tags":3144,"stars":3118,"repoUrl":3119,"updatedAt":3155},"jira-sprint-dashboard","create Jira sprint dashboards","Create a visual Jira sprint dashboard from Jira project, space, sprint, board, filter, JQL, work item keys, or Jira URL data. Use when the user asks for a Jira sprint dashboard, standup dashboard, sprint review, delivery review, engineering manager dashboard, WIP review, planning view, closeout view, or a visual snapshot of Jira work that is more useful than a flat report. Use the richest dashboard format supported by the current agent, such as Cursor Canvas, an interactive artifact, HTML, or Markdown.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3145,3148,3151,3152],{"name":3146,"slug":3147,"type":15},"Agile","agile",{"name":3149,"slug":3150,"type":15},"Dashboards","dashboards",{"name":2457,"slug":3111,"type":15},{"name":3153,"slug":3154,"type":15},"Sprint Planning","sprint-planning","2026-07-12T07:58:41.031798",{"slug":3157,"name":3157,"fn":3158,"description":3159,"org":3160,"tags":3161,"stars":3118,"repoUrl":3119,"updatedAt":3168},"search-company-knowledge","search internal company knowledge bases","Search across company knowledge bases (Confluence, Jira, internal docs) to find and explain internal concepts, processes, and technical details. When an agent needs to: (1) Find or search for information about systems, terminology, processes, deployment, authentication, infrastructure, architecture, or technical concepts, (2) Search internal documentation, knowledge base, company docs, or our docs, (3) Explain what something is, how it works, or look up information, or (4) Synthesize information from multiple sources. Searches in parallel and provides cited answers.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3162,3163,3164,3165],{"name":3129,"slug":3130,"type":15},{"name":3062,"slug":3063,"type":15},{"name":2457,"slug":3111,"type":15},{"name":3166,"slug":3167,"type":15},"Knowledge Management","knowledge-management","2026-07-12T07:58:39.684132",{"slug":3170,"name":3170,"fn":3171,"description":3172,"org":3173,"tags":3174,"stars":3118,"repoUrl":3119,"updatedAt":3179},"spec-to-backlog","convert Confluence specifications to Jira backlogs","Automatically convert Confluence specification documents into structured Jira backlogs with Epics and implementation tickets. When an agent needs to: (1) Create Jira tickets from a Confluence page, (2) Generate a backlog from a specification, (3) Break down a spec into implementation tasks, or (4) Convert requirements into Jira issues. Handles reading Confluence pages, analyzing specifications, creating Epics with proper structure, and generating detailed implementation tickets linked to the Epic.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3175,3176,3177,3178],{"name":3146,"slug":3147,"type":15},{"name":3129,"slug":3130,"type":15},{"name":2457,"slug":3111,"type":15},{"name":3133,"slug":3134,"type":15},"2026-07-12T07:58:37.200385",{"slug":3181,"name":3181,"fn":3182,"description":3183,"org":3184,"tags":3185,"stars":3118,"repoUrl":3119,"updatedAt":3192},"triage-issue","triage bug reports in Jira","Intelligently triage bug reports and error messages by searching for duplicates in Jira and offering to create new issues or add comments to existing ones. When an agent needs to: (1) Triage a bug report or error message, (2) Check if an issue is a duplicate, (3) Find similar past issues, (4) Create a new bug ticket with proper context, or (5) Add information to an existing ticket. Searches Jira for similar issues, identifies duplicates, checks fix history, and helps create well-structured bug reports.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3186,3187,3188,3189],{"name":18,"slug":19,"type":15},{"name":2457,"slug":3111,"type":15},{"name":3133,"slug":3134,"type":15},{"name":3190,"slug":3191,"type":15},"Triage","triage","2026-07-12T07:58:33.007343",{"slug":3020,"name":3020,"fn":3021,"description":3022,"org":3194,"tags":3195,"stars":20,"repoUrl":21,"updatedAt":3033},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3196,3197,3198,3199],{"name":9,"slug":8,"type":15},{"name":3027,"slug":3028,"type":15},{"name":13,"slug":14,"type":15},{"name":3031,"slug":3032,"type":15},{"slug":3035,"name":3035,"fn":3036,"description":3037,"org":3201,"tags":3202,"stars":20,"repoUrl":21,"updatedAt":3048},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3203,3204,3205,3206],{"name":9,"slug":8,"type":15},{"name":3042,"slug":3043,"type":15},{"name":13,"slug":14,"type":15},{"name":3046,"slug":3047,"type":15},{"slug":3050,"name":3050,"fn":3051,"description":3052,"org":3208,"tags":3209,"stars":20,"repoUrl":21,"updatedAt":3064},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3210,3211,3212],{"name":3056,"slug":3057,"type":15},{"name":3059,"slug":3060,"type":15},{"name":3062,"slug":3063,"type":15},{"slug":3066,"name":3066,"fn":3067,"description":3068,"org":3214,"tags":3215,"stars":20,"repoUrl":21,"updatedAt":3078},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3216,3217,3218],{"name":9,"slug":8,"type":15},{"name":3073,"slug":3074,"type":15},{"name":3076,"slug":3077,"type":15},{"slug":4,"name":4,"fn":5,"description":6,"org":3220,"tags":3221,"stars":20,"repoUrl":21,"updatedAt":22},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3222,3223,3224],{"name":9,"slug":8,"type":15},{"name":18,"slug":19,"type":15},{"name":13,"slug":14,"type":15},{"slug":3086,"name":3086,"fn":3087,"description":3088,"org":3226,"tags":3227,"stars":20,"repoUrl":21,"updatedAt":3098},{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[3228,3229,3230],{"name":3092,"slug":3093,"type":15},{"name":3042,"slug":3043,"type":15},{"name":3096,"slug":3097,"type":15},24]