datalayer / jupyter-ui

⚛️ React.js components 💯% compatible with 🪐 Jupyter https://jupyter-ui-storybook.datalayer.tech
https://jupyter-ui.datalayer.tech
Other
346 stars 47 forks source link

JupyterLab widget crash with NPE in Output when using display() in python code #321

Open sok82 opened 1 month ago

sok82 commented 1 month ago

Description

Dynamically added Output component crashes on rendering output with NPE when display_data output received

Exception stack trace is

[debug] Got new output for id=46dfb063-98cb-4eb0-8e4f-4c6005aea218 and phase=RUNNING(Thu Oct 17 2024 16:16:19 GMT+0300 (Moscow Standard Time))

widget.ts:154 Uncaught (in promise) TypeError: Cannot read properties of null (reading 'widgets')
    at get widgets (widget.ts:154:1)
    at set future (widget.ts:206:1)
    at execute (OutputExecutor.ts:45:1)
    at OutputAdapter.execute (OutputAdapter.ts:105:1)
    at Output.tsx:155:1
    at commitHookEffectListMount (react-dom.development.js:23189:1)
    at commitPassiveMountOnFiber (react-dom.development.js:24965:1)
    at commitPassiveMountEffects_complete (react-dom.development.js:24930:1)
    at commitPassiveMountEffects_begin (react-dom.development.js:24917:1)
    at commitPassiveMountEffects (react-dom.development.js:24905:1)

KernelExecutor.ts:153 [debug] Got new output for id=46dfb063-98cb-4eb0-8e4f-4c6005aea218 and phase=COMPLETED (data : [{"output_type":"display_data","data":{"text/plain":"np.float64(0.5339950000000001)"},"metadata":{}}])(Thu Oct 17 2024 16:16:42 GMT+0300 (Moscow Standard Time))

In case when output is already present in the component tree - everything works fine

Reproduce

...Investigating

sok82 commented 1 month ago

Exception occurs in @jupyterlab/OutputArea component due to layout is not initialized at some point in time when root Widget component tries to render display_data

See source code below

/** ****************************************************************************
 * OutputArea
 ******************************************************************************/

/**
 * An output area widget.
 *
 * #### Notes
 * The widget model must be set separately and can be changed
 * at any time.  Consumers of the widget must account for a
 * `null` model, and may want to listen to the `modelChanged`
 * signal.
 */
export class OutputArea extends Widget {
  /**
   * Construct an output area widget.
   */
  constructor(options: OutputArea.IOptions) {
    super();
    super.layout = new PanelLayout();
….
  }
....
/**
   * A read-only sequence of the children widgets in the output area.
   */
  get widgets(): ReadonlyArray<Widget> {
    return this.layout.widgets;
  }