Skip to content

Fix crashes, modernize dependencies, improve editor reliability#25

Open
dxdc wants to merge 12 commits into
sammachin:mainfrom
dxdc:fix/stability-and-modernization
Open

Fix crashes, modernize dependencies, improve editor reliability#25
dxdc wants to merge 12 commits into
sammachin:mainfrom
dxdc:fix/stability-and-modernization

Conversation

@dxdc
Copy link
Copy Markdown

@dxdc dxdc commented Mar 20, 2026

Summary

This PR fixes multiple Node-RED-crashing bugs, updates the Matter SDK from 0.11.9 to 0.16.11, overhauls the editor UI for reliable cascading dropdowns, fills missing cluster definitions, and adds device discovery methods.

Note: The node_modules/ removal is in a separate PR.

Breaking Changes

  • Node.js 20.19+ required - matter.js 0.16 dropped Node 18.
  • New fabricLabel config field - existing configs continue to work (defaults to the controller Name).
  • Version bumped to 0.2.0.

Crash Fixes

command is not a function fatal error - All cluster method lookups used eval() which returned undefined for nonexistent methods, then calling undefined() killed Node-RED. Replaced with bracket notation plus typeof guards across 6 files.

Decommission crash during reconnect - conn.decommission() had no .catch(). The error from attempting to decommission a reconnecting device was unhandled and crashed Node-RED.

Null controller crashes - RED.nodes.getNode() returns null if the controller is deleted or undeployed. Every node immediately dereferenced it without checking.

BigInt crash on unconfigured nodes - BigInt("") and BigInt("__SELECT__") throw SyntaxError. Event and subscribe nodes parse the device ID at creation time, so a half-configured node crashed Node-RED on deploy.

command.js Object.keys(undefined) - If evaluateNodeProperty errored, execution continued with _data as undefined. Also failed on non-object types like strings.

command.js missing endpoint fallback - The only node without || 1 on split('-')[1]. Simple devices got getDeviceById(NaN) → null → crash.

Matter SDK UDP "Not running" crash - The SDK throws from inside a Promise constructor when the dgram socket closes during CASE session teardown on redeploy. Added a process.uncaughtException handler scoped to @matter//@project-chip/ stack frames that logs these as warnings instead of crashing.

Matter SDK CASE Sigma2 rejection crash - Added a matching process.unhandledRejection handler for promise rejections originating in the SDK's session resumption layer (e.g. CASE Sigma2 errors), which would otherwise crash Node-RED as unhandled rejections.

Unhandled promise rejections - connectNode() calls across all node types and editor API endpoints lacked .catch() handlers.

simpleMode dropdown crash - setCommand() and setAttribute() called simpleCommands[cluster].includes() and simpleAttributes[cluster].includes() without null-checking the lookup first. When a cluster had no entry in the simpleCommands/simpleAttributes objects, this threw TypeError: Cannot read properties of undefined. Added guards matching the existing safe pattern in getCommands()/getAttributes().

The "Matter Test" Name Issue

Two independent bugs:

  1. Controller name never saved - Template used id="node-input-name" but config nodes require node-config-input- prefix.
  2. No adminFabricLabel passed to SDK - Added a new "Fabric Label" config field, falls back to Name.

Editor UI Overhaul

Cascading dropdowns - Selecting a controller auto-populates devices, selecting a device auto-populates clusters, selecting a cluster auto-populates commands/attributes/events. Uses an initialization guard flag (_initDone set after 500ms) so the cascade handlers don't fire during editor open and wipe saved values from async restoration.

Empty-state feedback - Clusters with no events show "No events available for this cluster" as a disabled option instead of just --SELECT--.

Node labels - Added isRealValue() and getSelectedText() helpers. Labels only show deviceName | field when both are genuine values. oneditsave uses getSelectedText() instead of blindly reading innerHTML, preventing --SELECT-- from leaking into labels.

Runtime deploy-time feedback - Rather than editor validation (which fundamentally conflicts with async-populated selects), incomplete configs are caught on deploy with status indicators: red "no controller", yellow "not configured", red "invalid event"/"invalid attribute".

Broken jQuery selectors fixed - $('node-input-command') missing #, $('node-input-attribute') referencing wrong ID, both using nonexistent "changed" event.

Other editor fixes - simpleMode checkbox not persisting on Event nodes, tautological ||/&& guard conditions (8 occurrences), toggleMethod not called on editor open, missing methodType default, device list race conditions with shared globals, 30-second timeout for unreachable devices, clearSelect vs resetSelect to avoid clobbering downstream values.

New Features

listEndpoints manager method - Returns all endpoints on a device with their device types, names, and cluster summaries (id + name). Useful for discovering what a device exposes without needing the full attribute/command detail.

describe manager method - Returns the complete device structure: all endpoints, each with their clusters, and each cluster with its full list of attributes and commands. Wire inject → mattermanager (describe) → debug to discover exactly what a device supports - helpful for finding clusters like RelativeHumidityMeasurement (1029) on unexpected endpoints.

Missing Cluster Definitions Filled

The simpleCommands and simpleAttributes objects were missing entries for many clusters listed in simpleClusters, causing the simpleMode filter to hide all options for those clusters. All entries verified against the Matter SDK source in node_modules/@matter/types/src/clusters/.

simpleCommands added: 28 (PulseWidthModulation), 72 (OvenCavityOperationalState), 73 (OvenMode), 81 (LaundryWasherMode), 82 (RefrigeratorMode), 84 (RvcRunMode), 85 (RvcCleanMode), 89 (DishwasherMode), 157 (EnergyEvseMode), 159 (DeviceEnergyManagementMode)

simpleAttributes added: 28 (PulseWidthModulation), 31 (AccessControl), 72 (OvenCavityOperationalState), 73 (OvenMode), 87 (RefrigeratorAlarm), 93 (DishwasherAlarm), 97 (RvcOperationalState), 113 (HepaFilterMonitoring), 114 (ActivatedCarbonFilterMonitoring), 157 (EnergyEvseMode), 159 (DeviceEnergyManagementMode), 1036–1071 (all ConcentrationMeasurement clusters: CO, CO₂, NO₂, O₃, PM2.5, formaldehyde, PM1, PM10, TVOC, radon)

Dependency Updates

  • @matter/main: ^0.11.9^0.16.11
  • @project-chip/matter.js: ^0.11.9^0.16.11

All runtime APIs verified compatible. Removed 20+ unused imports from controller.js and manager.js (copy-pasted from the TypeScript example file, never referenced at runtime).

Housekeeping

  • Removed "main": "index.js" (no such file), added "files" field for npm publish
  • Added node.on('close') handlers for clean shutdown on controller, event, subscribe
  • Declared implicit globals with let/const throughout
  • Fixed stray 1 expression after break; in controller.js
  • Fixed typos: commissioning (×4), decommission, subscriptions
  • Fixed write_attribute label returning "Read" instead of "Write Attribute"
  • Fixed subscribe label fallback from "Read" to "Subscribe"
  • Fixed cluser typo in editor.js global declarations
  • Removed debug console.log statements, upgraded error logs to console.warn
  • Used done() callback in command.js for proper catch node support
  • Moved getCommandOpts() inside async callback (was firing before dropdown populated)

@dxdc dxdc force-pushed the fix/stability-and-modernization branch from 1c479ec to cb7d5cb Compare March 20, 2026 20:16
@dxdc dxdc force-pushed the fix/stability-and-modernization branch from b5d5372 to 2cfc6fe Compare April 13, 2026 03:37
@dxdc
Copy link
Copy Markdown
Author

dxdc commented Apr 13, 2026

heads up, massive pr here, but I think I caught all of the major bugs from the earlier version. I reorganized everything by feature/commit to make it a lot easier to review.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant