[GH-ISSUE #199] Adding an item in the middle of a list causes the react renderer to crash #813

Closed
opened 2026-03-14 08:39:47 +03:00 by kerem · 0 comments
Owner

Originally created by @eli0shin on GitHub (Oct 5, 2025).
Original GitHub issue: https://github.com/anomalyco/opentui/issues/199

When a list is rendered (I've seen this in scrollbox and in regular boxes) if an item is added in the middle of the list the renderer crashes with the following error:

Error: Anchor does not exist                                                                                                                          
    at insertBefore (/Users/elioshinsky/code/opentui/packages/core/src/Renderable.ts:1118:17)                                                         
    at insertBefore (/Users/elioshinsky/code/opentui/packages/react/src/reconciler/host-config.ts:65:12)                                              
    at insertOrAppendPlacementNode (/Users/elioshinsky/code/opentui/node_modules/react-reconciler/cjs/react-reconciler.development.js:9987:15)        
    at commitPlacement (/Users/elioshinsky/code/opentui/node_modules/react-reconciler/cjs/react-reconciler.development.js:10041:13)                   
    at runWithFiberInDEV (/Users/elioshinsky/code/opentui/node_modules/react-reconciler/cjs/react-reconciler.development.js:1738:13)                  
    at commitReconciliationEffects (/Users/elioshinsky/code/opentui/node_modules/react-reconciler/cjs/react-reconciler.development.js:11090:11)       
    at commitMutationEffectsOnFiber (/Users/elioshinsky/code/opentui/node_modules/react-reconciler/cjs/react-reconciler.development.js:10810:11)      
    at recursivelyTraverseMutationEffects (/Users/elioshinsky/code/opentui/node_modules/react-reconciler/cjs/react-reconciler.development.js:10692:11)
    at commitMutationEffectsOnFiber (/Users/elioshinsky/code/opentui/node_modules/react-reconciler/cjs/react-reconciler.development.js:10809:11)      
    at recursivelyTraverseMutationEffects (/Users/elioshinsky/code/opentui/node_modules/react-reconciler/cjs/react-reconciler.development.js:10692:11)

I extended the react scroll example to add a new item to the middle of the list after 3 seconds and added an Error Boundary to render the error. Here is the code to reproduce it reliably.
If you remove the last box after the extra one the renderer does not crash.

import { render } from "@opentui/react"
import { useState, useEffect, Component } from "react"
import type { ReactNode } from "react"

type ErrorBoundaryProps = {
  children: ReactNode
}

type ErrorBoundaryState = {
  hasError: boolean
  error?: Error
}

class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
  constructor(props: ErrorBoundaryProps) {
    super(props)
    this.state = { hasError: false }
  }

  static getDerivedStateFromError(error: Error): ErrorBoundaryState {
    return { hasError: true, error }
  }

  componentDidCatch(error: Error, errorInfo: unknown) {
    console.error("Error caught by boundary:", error, errorInfo)
  }

  render() {
    if (this.state.hasError) {
      return (
        <box style={{ padding: 2 }}>
          <text content={`${this.state.error?.stack || "Unknown error"}`} />
        </box>
      )
    }

    return this.props.children
  }
}

export const App = () => {
  const [extra, setExtra] = useState(false)
  useEffect(() => {
    setTimeout(() => {
      setExtra(true)
    }, 3_000)
  }, [])
  return (
    <ErrorBoundary>
      <scrollbox
        style={{
          rootOptions: {
            backgroundColor: "#24283b",
          },
          wrapperOptions: {
            backgroundColor: "#1f2335",
          },
          viewportOptions: {
            backgroundColor: "#1a1b26",
          },
          contentOptions: {
            backgroundColor: "#16161e",
          },
          scrollbarOptions: {
            showArrows: true,
            trackOptions: {
              foregroundColor: "#7aa2f7",
              backgroundColor: "#414868",
            },
          },
        }}
        focused
      >
        {Array.from({ length: 1000 }).map((_, i) => (
          <box
            key={i}
            style={{ width: "100%", padding: 1, marginBottom: 1, backgroundColor: i % 2 === 0 ? "#292e42" : "#2f3449" }}
          >
            <text content={`Box ${i}`} />
          </box>
        ))}
        {extra ? (
          <box key={`extra`} style={{ width: "100%", padding: 1, marginBottom: 1, backgroundColor: "#292e42" }}>
            <text content={`Box extra`} />
          </box>
        ) : null}
        <box style={{ width: "100%", padding: 1, marginBottom: 1, backgroundColor: "#292e42" }}>
          <text content={`Box constant`} />
        </box>
      </scrollbox>
    </ErrorBoundary>
  )
}

render(<App />)
Originally created by @eli0shin on GitHub (Oct 5, 2025). Original GitHub issue: https://github.com/anomalyco/opentui/issues/199 When a list is rendered (I've seen this in scrollbox and in regular boxes) if an item is added in the middle of the list the renderer crashes with the following error: ``` Error: Anchor does not exist at insertBefore (/Users/elioshinsky/code/opentui/packages/core/src/Renderable.ts:1118:17) at insertBefore (/Users/elioshinsky/code/opentui/packages/react/src/reconciler/host-config.ts:65:12) at insertOrAppendPlacementNode (/Users/elioshinsky/code/opentui/node_modules/react-reconciler/cjs/react-reconciler.development.js:9987:15) at commitPlacement (/Users/elioshinsky/code/opentui/node_modules/react-reconciler/cjs/react-reconciler.development.js:10041:13) at runWithFiberInDEV (/Users/elioshinsky/code/opentui/node_modules/react-reconciler/cjs/react-reconciler.development.js:1738:13) at commitReconciliationEffects (/Users/elioshinsky/code/opentui/node_modules/react-reconciler/cjs/react-reconciler.development.js:11090:11) at commitMutationEffectsOnFiber (/Users/elioshinsky/code/opentui/node_modules/react-reconciler/cjs/react-reconciler.development.js:10810:11) at recursivelyTraverseMutationEffects (/Users/elioshinsky/code/opentui/node_modules/react-reconciler/cjs/react-reconciler.development.js:10692:11) at commitMutationEffectsOnFiber (/Users/elioshinsky/code/opentui/node_modules/react-reconciler/cjs/react-reconciler.development.js:10809:11) at recursivelyTraverseMutationEffects (/Users/elioshinsky/code/opentui/node_modules/react-reconciler/cjs/react-reconciler.development.js:10692:11) ``` I extended the react scroll example to add a new item to the middle of the list after 3 seconds and added an Error Boundary to render the error. Here is the code to reproduce it reliably. If you remove the last box after the extra one the renderer does not crash. ```typescript import { render } from "@opentui/react" import { useState, useEffect, Component } from "react" import type { ReactNode } from "react" type ErrorBoundaryProps = { children: ReactNode } type ErrorBoundaryState = { hasError: boolean error?: Error } class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> { constructor(props: ErrorBoundaryProps) { super(props) this.state = { hasError: false } } static getDerivedStateFromError(error: Error): ErrorBoundaryState { return { hasError: true, error } } componentDidCatch(error: Error, errorInfo: unknown) { console.error("Error caught by boundary:", error, errorInfo) } render() { if (this.state.hasError) { return ( <box style={{ padding: 2 }}> <text content={`${this.state.error?.stack || "Unknown error"}`} /> </box> ) } return this.props.children } } export const App = () => { const [extra, setExtra] = useState(false) useEffect(() => { setTimeout(() => { setExtra(true) }, 3_000) }, []) return ( <ErrorBoundary> <scrollbox style={{ rootOptions: { backgroundColor: "#24283b", }, wrapperOptions: { backgroundColor: "#1f2335", }, viewportOptions: { backgroundColor: "#1a1b26", }, contentOptions: { backgroundColor: "#16161e", }, scrollbarOptions: { showArrows: true, trackOptions: { foregroundColor: "#7aa2f7", backgroundColor: "#414868", }, }, }} focused > {Array.from({ length: 1000 }).map((_, i) => ( <box key={i} style={{ width: "100%", padding: 1, marginBottom: 1, backgroundColor: i % 2 === 0 ? "#292e42" : "#2f3449" }} > <text content={`Box ${i}`} /> </box> ))} {extra ? ( <box key={`extra`} style={{ width: "100%", padding: 1, marginBottom: 1, backgroundColor: "#292e42" }}> <text content={`Box extra`} /> </box> ) : null} <box style={{ width: "100%", padding: 1, marginBottom: 1, backgroundColor: "#292e42" }}> <text content={`Box constant`} /> </box> </scrollbox> </ErrorBoundary> ) } render(<App />) ```
kerem 2026-03-14 08:39:47 +03:00
  • closed this issue
  • added the
    bug
    react
    labels
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/opentui#813
No description provided.