{"record":{"id":"3528d1dc690d7540","repo":"NativeScript/NativeScript","slug":"view-not-registered","errorCode":null,"errorMessage":"View not registered","messagePattern":"View not registered","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/ui/list-view/index.android.ts","lineNumber":116,"sourceCode":"\n\tpublic _registerViewToTemplate(templateKey: string, nativeView: android.view.View, view: View) {\n\t\tthis._realizedItems.set(nativeView, {\n\t\t\tview,\n\t\t\ttemplateKey,\n\t\t});\n\t\tif (!this._realizedTemplates.has(templateKey)) {\n\t\t\tthis._realizedTemplates.set(templateKey, new Map());\n\t\t}\n\t\tthis._realizedTemplates.get(templateKey).set(nativeView, view);\n\t\tthis._ensureAvailableViews(templateKey);\n\t\tconst availableViews = this._availableViews.get(templateKey);\n\t\tavailableViews.add(nativeView);\n\t}\n\n\tpublic _markViewUsed(nativeView: android.view.View) {\n\t\tconst viewData = this._realizedItems.get(nativeView);\n\t\tif (!viewData) {\n\t\t\tthrow new Error('View not registered');\n\t\t}\n\t\tthis._ensureAvailableViews(viewData.templateKey);\n\t\tthis._availableViews.get(viewData.templateKey).delete(nativeView);\n\t}\n\tpublic _markViewUnused(nativeView: android.view.View) {\n\t\tconst viewData = this._realizedItems.get(nativeView);\n\t\tif (!viewData) {\n\t\t\tthrow new Error('View not registered');\n\t\t}\n\t\tthis._ensureAvailableViews(viewData.templateKey);\n\t\tthis._availableViews.get(viewData.templateKey).add(nativeView);\n\t}\n\tpublic _getKeyFromView(nativeView: android.view.View) {\n\t\treturn this._realizedItems.get(nativeView).templateKey;\n\t}\n\tpublic _hasAvailableView(templateKey: string) {\n\t\tthis._ensureAvailableViews(templateKey);\n\t\treturn this._availableViews.get(templateKey).size > 0;","sourceCodeStart":98,"sourceCodeEnd":134,"githubUrl":"https://github.com/NativeScript/NativeScript/blob/6800aefa6511d23ddad8beb38ccc8541c5e91628/packages/core/ui/list-view/index.android.ts#L98-L134","documentation":"On Android, ListView reuses (recycles) native views. `_markViewUsed` looks up a native android.view.View in the internal `_realizedItems` map to move it from the available pool to in-use; if the view was never realized/registered by the ListView's adapter, the lookup returns nothing and this Error is thrown. It is called from `_getAvailableView`, so it surfaces during item view acquisition while scrolling or loading items.","triggerScenarios":"A native view reaches `_getAvailableView` without having gone through the adapter's realization path — e.g. custom adapter overrides that bypass `_realizedItems` registration, view pool manipulation, or item views created outside `ListView`'s `_onLoadingItem`/realization flow.","commonSituations":"Subclassing or patching the Android ListView adapter and recycling views manually; native plugin interop that reuses views across ListView instances; race conditions during fast scrolling with itemTemplateSelector changes; fragment/activity recreation reusing stale native views.","solutions":["Do not create or recycle item views manually on Android — let the ListView adapter realize them so they get registered in `_realizedItems`.","Update to a recent @nativescript/core version; several ListView recycling fixes have landed upstream.","If you have a custom adapter override, ensure every view it returns is registered via the base class realization flow (i.e. call super / go through the standard template realization).","Avoid sharing the same item view instances between multiple ListView instances or templates."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"let view: android.view.View;\ntry {\n  view = listView._getAvailableView(templateKey);\n} catch (e) {\n  if (e.message === 'View not registered') {\n    view = null; // fall back to normal realization\n  } else {\n    throw e;\n  }\n}","typeGuard":"const isRegistered = (lv: any, v: android.view.View): boolean =>\n  lv._realizedItems && lv._realizedItems.has(v);","tryCatchPattern":"try {\n  this._markViewUsed(nativeView);\n} catch (e) {\n  if (e.message === 'View not registered') {\n    // re-realize through the standard adapter path instead of reusing\n    return this.rematerializeItemView(nativeView);\n  }\n  throw e;\n}","preventionTips":["Never bypass the ListView adapter's view realization path on Android.","Don't share native item views across ListView instances, templates, or template selectors.","Keep @nativescript/core updated; recycling bugs are regularly patched.","Test template-selector changes and fast scrolling, the most common repro triggers."],"tags":["android","listview","view-recycling","internal-state"],"backgroundTag":"view-not-registered","analyzedSha":"6800aefa6511d23ddad8beb38ccc8541c5e91628","analyzedAt":"2026-08-30T20:04:56.809Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}