Skip to content

Troubleshooting

This document catalogs known Forge platform bugs, common deployment failures, and their solutions. Each issue follows the format: Problem -> Cause -> Solution.

These are open bugs in the Atlassian ECO Jira project that affect Foundation. A full audit of 80+ bugs is available at docs/plans/2026-03-17-forge-platform-bugs-audit.md.

ECO-1310 / ECO-1346: CaaS Manifest Byte Size Limit

Section titled “ECO-1310 / ECO-1346: CaaS Manifest Byte Size Limit”

Problem: Forge deploy fails during “Release CaaS manifest” with INTERNAL_SERVER_ERROR 500 when the manifest exceeds the CaaS byte limit.

Cause: The Forge CaaS manifest conversion has a hard limit of ~257KB after internal conversion. The CaaS conversion inflates raw manifest bytes by 8-10x, giving a practical raw byte ceiling of ~23,500 bytes.

Solution:

  • Use the slim manifest format: descriptions=., titles=x, 2-char function keys, no optional fields.
  • Run cd foundation && npm run check:manifest before adding any new action.
  • Current state: 35 actions, ~22,850 bytes, ~650 bytes of headroom.
  • If more actions are needed, consolidate via dispatcher functions (route multiple logical actions through one manifest entry with an _action parameter).

ECO-1090: Forge SQL Returns 5xx Instead of 429 for Rate Limits

Section titled “ECO-1090: Forge SQL Returns 5xx Instead of 429 for Rate Limits”

Problem: SQL operations fail with 5xx errors that look like server failures but are actually rate limit violations.

Cause: When the Forge SQL rate limit (150 DML/second) is exceeded, the platform returns 5xx instead of 429. Application error handling cannot distinguish rate limits from real failures.

Solution:

  • Currently no client-side workaround. Treat all 5xx from SQL operations as potentially rate-limit related.
  • Implement exponential backoff on SQL 5xx errors.
  • Atlassian has a fix in progress to return proper 429 responses. Once shipped, update error handling in cache-manager.ts and all SQL-touching services.

ECO-395: Missing Events for Custom Workflow Notifications

Section titled “ECO-395: Missing Events for Custom Workflow Notifications”

Problem: The issue cache goes stale silently. Users see outdated status, assignee, or priority data for up to 60 minutes.

Cause: avi:jira:updated:issue does NOT fire when a Jira workflow transition uses Custom Event Notifications. The event-driven cache sync has no way to detect these updates.

Solution:

  • No workaround exists. This is a gap in the cache freshness model.
  • The hourly cache integrity scheduled trigger (cic) is the safety net, limiting the stale window to ~60 minutes.
  • Document this as a known limitation for customers using custom workflow events.

ECO-1356 / ECO-1198: Stale Context After SPA Navigation

Section titled “ECO-1356 / ECO-1198: Stale Context After SPA Navigation”

Problem: The issue context panel shows data for the wrong issue after navigating between issues without a full page reload.

Cause: view.getContext() and resolver context return the previous page’s extension data after SPA navigation. This affects both useProductContext() and direct view.getContext() calls.

Solution:

  • Verify context.extension.issue.key matches the expected issue before rendering.
  • Refreshing the page reloads the context correctly.
  • Add a context-key guard in the issue context panel component.

ECO-277: Resolver undefined Becomes {} on Frontend

Section titled “ECO-277: Resolver undefined Becomes {} on Frontend”

Problem: Frontend if (!data) checks fail to detect “no data” conditions. Components render when they should show empty states.

Cause: Any resolver that returns undefined (e.g., entity not found, empty result) is received by the frontend as {} (truthy). The Forge bridge coerces undefined to an empty object.

Solution:

  • Never return bare undefined from resolvers.
  • Always return explicit null, false, or { data: null }.
  • Audit all resolvers for bare undefined returns.

Section titled “ECO-1297: False Re-Consent Prompt on 401 from Jira APIs”

Problem: Users see a confusing consent/re-authorization dialog when the actual issue is a permission error.

Cause: When asUser() Jira API calls return 401 (permission denied, expired session), Forge shows a consent dialog instead of passing the error through.

Solution:

  • Wrap all api.asUser() calls in try/catch.
  • Return controlled error objects instead of propagating raw API results.
  • Foundation already does this in most resolvers.

ECO-1222: ADMINISTER Permission Not Recognized

Section titled “ECO-1222: ADMINISTER Permission Not Recognized”

Problem: overrideEditableFlag and overrideScreenSecurity fail when using asUser() even with ADMINISTER permission.

Cause: These Jira API features only work with asApp(), not asUser(). This is a platform-level limitation.

Solution:

  • Use asApp() with explicit permission validation in app code for admin-level operations.

ECO-1307: Reserved Key “schema” in Resolver Payloads

Section titled “ECO-1307: Reserved Key “schema” in Resolver Payloads”

Problem: Resolver invocations fail with a schema validation error.

Cause: The Forge bridge validates payloads and rejects invocations that contain "schema" as a top-level key.

Solution:

  • Never use "schema" as a key in resolver payloads.
  • Rename any payload keys that might collide.

ECO-508: Missing changelog in Issue Updated Events

Section titled “ECO-508: Missing changelog in Issue Updated Events”

Problem: Issue update events sometimes lack the changelog field, forcing a full issue re-fetch (2 rate limit points per event).

Cause: When generateChangelog=false (triggered by certain API calls), the changelog is omitted from the event payload.

Solution:

  • Always fall back to full issue re-fetch when changelog is absent.
  • Budget for extra API calls in rate limit calculations.

BugProblemSolution
ECO-1321postrobot_method console error when navigating away from FoundationCosmetic only; no fix needed
ECO-1355Admin page not clickable with custom domainsUse standard .atlassian.net domain
ECO-1246Missing entity properties in trigger event payloadsMake additional API calls per event
ECO-1174Chrome Local Network Access blocks Custom UI fetchUsers disable Chrome flag or use Firefox
ECO-303Icons not loaded in Custom UI on FirefoxUsers disable Enhanced Tracking Protection
ECO-226jira:globalPage broken for JSM “customer” users with Jira licenseNo workaround
ECO-1280--ds-radius-*, --ds-font-* tokens not set by view.theme.enable()Use hardcoded fallbacks in CSS
ECO-1309Project icon avatar returns 403Fall back to default project icons

Problem: Frontend build fails with compilation errors.

Solution:

  1. Check for TypeScript errors: cd foundation && npx tsc --noEmit
  2. Check for missing dependencies: cd foundation/static/main && npm install
  3. Verify .npmrc exists in all four packages with legacy-peer-deps=true

Problem: forge deploy fails at “Release CaaS manifest” with 500 error.

Cause: Either the manifest exceeds the byte limit (ECO-1310) or the environment is corrupted.

Solution:

  1. Check manifest size: cd foundation && npm run check:manifest
  2. If manifest is within budget, the environment is likely corrupted.
  3. Test in a different environment: forge deploy --environment staging
  4. If another environment succeeds, create a fresh one:
    Terminal window
    cd foundation && forge environments create --environment dev-new --non-interactive
    cd foundation && forge deploy --environment dev-new
    cd foundation && forge settings set default-environment dev-new

Problem: Forge CLI cannot find manifest.yml.

Cause: Running from the wrong directory.

Solution: Always run Forge commands from the foundation/ directory, not the repository root.


Problem: Deploy script exits with “Deploy blocked: running from a git worktree.”

Cause: The deploy.sh script detects it’s running from a git worktree.

Solution: Merge your worktree branch back to main, then deploy from the main working tree.


Problem: forge install fails on a Jira site.

Cause: The manifest has too many actions/modules, or there’s a conflict with a previous installation.

Solution:

  1. Check if the old installation is still present: forge install list
  2. Uninstall the old one from Jira admin panel if needed (destructive — get user approval)
  3. Verify the manifest action count is within limits
  4. Retry installation

Problem: Build or test commands fail with “Cannot find module” errors in a worktree.

Cause: Worktree node_modules symlinks point to the wrong path (project was moved or cloned elsewhere).

Solution:

  1. The setup-worktree.sh hook should auto-detect and fix stale symlinks before every Bash command.
  2. If it doesn’t resolve:
    Terminal window
    # Remove the stale symlink manually
    rm foundation/node_modules
    rm foundation/static/main/node_modules
    # Re-run any command to trigger the hook, or run the script directly
    bash .claude/hooks/setup-worktree.sh

Problem: git status shows node_modules as a tracked file.

Cause: .gitignore has node_modules/ (with trailing slash) which matches directories but NOT symlinks. Git treats symlinks as files.

Solution:

  • .gitignore must use node_modules (no trailing slash) to match both directories and symlinks.
  • Remove any tracked symlinks: git rm --cached foundation/node_modules (and similar for sub-packages).

Problem: Worktree hooks fail because the main tree node_modules is a symlink instead of a real directory.

Cause: An incorrect setup or a stale worktree symlink was created in the main tree.

Solution:

  • The main tree’s node_modules must always be a real directory from npm install.
  • Remove the symlink and reinstall:
    Terminal window
    rm foundation/node_modules
    cd foundation && npm install

Problem: Hover highlights appear below the last data row in empty grid space.

Cause: AG Grid has a JS-based hover system (.ag-row-hover class) that calculates hover position from Y coordinates. It fires even in empty viewport space because AG Grid computes a virtual row index regardless of whether a row exists.

Solution:

  • suppressRowHoverHighlight={true} on <AgGridReact> disables the JS hover system.
  • Set --ag-row-hover-color: transparent to prevent residual AG Grid hover styling.
  • Implement hover via CSS .ag-row:hover in foundation.css (only fires on actual DOM elements).
  • Never re-enable AG Grid’s JS hover or set --ag-row-hover-color to a non-transparent value.

Problem: Cell editors close immediately after opening, or flicker and disappear.

Cause: stopEditingWhenCellsLoseFocus={true} is incompatible with Forge iframe — focus tracking breaks at the cross-origin boundary. Any useState setter in AG Grid editing callbacks causes a re-render that destroys the active editor.

Solution:

  • Set stopEditingWhenCellsLoseFocus={false}
  • Use useRef instead of useState for the isEditing flag
  • Zero state updates in AG Grid editing callbacks
  • Manual mousedown click-outside handler using a gridDivRef on the wrapper div

Problem: Dropdown editors (status, priority, assignee) don’t appear or appear at the wrong Y position.

Cause: AG Grid’s .ag-root-wrapper has overflow: hidden. When cellEditorPopup: true, the popup renders inside the wrapper and gets clipped. Additionally, AG Grid’s popup positioning is broken inside Forge iframes.

Solution:

  • Remove cellEditorPopup: true from status, priority, and assignee editors — render them inline instead.
  • For editors with custom DOM dropdowns (like AssigneePicker), use position: fixed on the dropdown and calculate coordinates from getBoundingClientRect().
  • Never use cellEditorPopup: true for editors with native <select> elements in a Forge iframe.

Click-Outside Handler Broken in AG Grid v35

Section titled “Click-Outside Handler Broken in AG Grid v35”

Problem: Click-outside detection for inline editors doesn’t work.

Cause: AG Grid v35 removed the eGridDiv property from AgGridReact. Code using gridRef.current?.eGridDiv gets undefined, making the click-outside handler a no-op.

Solution:

  • Use a gridDivRef on the wrapper div element instead of eGridDiv.
  • Attach mousedown listeners to document, checking if the event target is inside the grid wrapper.

Problem: SQL operations fail intermittently with 5xx errors that are difficult to diagnose.

Cause: Forge SQL rate limit violations (150 DML/second exceeded) return 5xx instead of 429 (ECO-1090). This makes rate limits indistinguishable from actual server failures.

Solution:

  • Implement exponential backoff on all SQL 5xx errors.
  • Monitor operation frequency and batch where possible.
  • The fix from Atlassian (proper 429 responses) is in progress. Once available, update error handling in cache-manager.ts and all SQL-touching services to handle 429 with appropriate backoff.

Problem: console.log statements in the frontend produce no visible output.

Cause: Forge iframe console messages don’t cross to the parent page. window.parent.postMessage is blocked by CSP.

Solution:

  • Use visible DOM elements (debug banners) rather than console.log.
  • Use large fonts (13px+), pre-wrap white-space, and word-break: break-all.
  • Remove debug elements before committing.

Browser-level screenshots CAN capture the content inside the Forge Custom UI iframe. Use screenshot tools to verify visual rendering after deployment.

Automated click interactions cannot reliably reach inside the Forge iframe. Interactive testing (clicking buttons, opening menus, filling forms) must be done manually by the user.