makeplane / makeplane/plane

iOS WebKit: gantt-layout-loader throws on missing window.requestIdleCallback — global error boundary on every issues-list view

Open
#9,231 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
59.6k
Forks
5.8k
Avg merge
1d 22h
Merged PRs (30d)
49

Description

Description

Plane CE's lazy-loaded gantt-layout-loader chunk calls window.requestIdleCallback without feature detection or a polyfill. iOS WebKit (Safari, iOS Chrome, iOS Firefox — all WebKit-backed under Apple's App Store rules) has never implemented requestIdleCallback — open WebKit gap since 2016 (webkit.org#164193). The throw propagates up, React's error boundary catches it, and the user sees the generic "Looks like something went wrong" page on every issues-list / project view.

Steps to reproduce
  1. iPad (any iOS / iPadOS version), Chrome (CriOS user-agent — but iOS Safari and iOS Firefox would all fail the same way; see "Why the matrix is weird" below).
  2. Sign in to a Plane CE instance.
  3. Navigate to any project's /projects/<uuid>/issues/ page.
  4. The full error boundary fires.
Console error (from Safari Web Inspector against the iPad)
TypeError: window.requestIdleCallback is not a function.
(In 'window.requestIdleCallback(()=>{h.current&&(S.current=`${h.current.offsetHeight}px`)})', 'window.requestIdleCallback' is undefined)
— gantt-layout-loader-BH8Iumhn.js:1:5524

React Router caught the following error during render
— componentDidCatch (chunk-EPOLDU6W-PsE1YSAx.js:4:2496)

[also] Minified React error #418 (hydration failed) and #423 (client-side recovery also failed)
— both downstream of the same throw.
Why the matrix is weird (and the cause is clear)
Browser Result Why
iOS Chrome (CriOS) Error boundary UA hints route through the bundle that lazy-loads gantt-layout-loader → hits missing API
iOS Safari Works UA routes through a different bundle that doesn't load the gantt chunk
iOS Chrome with "Request Desktop Site" Works Desktop UA routes through the desktop bundle (gantt chunk apparently feature-detects or skips on the desktop layout calculator path)
macOS Safari / macOS Chrome Works Engines implement requestIdleCallback natively

So the bug has been sitting hidden behind a UA-sniffing branch that only one of three iOS browser paths exercises.

Suggested fix

Either:

A — Polyfill requestIdleCallback once at app entry:

if (typeof window.requestIdleCallback !== 'function') {
  window.requestIdleCallback = (cb) => {
    const start = Date.now();
    return setTimeout(() => cb({
      didTimeout: false,
      timeRemaining: () => Math.max(0, 50 - (Date.now() - start)),
    }), 1);
  };
  window.cancelIdleCallback = (id) => clearTimeout(id);
}

B — Feature-detect inside gantt-layout-loader and fall back to setTimeout(fn, 0) for the height-measurement use case (which doesn't actually need idle-time semantics; it's just deferring a layout measurement).

Either is a few lines. (A) catches every other requestIdleCallback use in the codebase.

Environment
  • Plane CE v1.3.1 (self-hosted, full upstream image set)
  • Client: iPad (any), Chrome on iOS / iOS WebKit

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Locate the source for the lazy-loaded gantt-layout-loader and the application entry point, then reproduce the failure on an iOS WebKit browser using the project's issues-list or project view. Choose the fallback approach that fits the existing structure; done means the view renders without the global error boundary when requestIdleCallback is unavailable.

Written by the indexing model from the issue text.

Assessment

Tech stack
react, typescript
Domain
frontend, web-dev
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
64/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.