# Surgical Fix Report: Work Order Start Tracking Error ## Date: November 27, 2025 ## Strategy: Diagnosis → Plan → Implementation --- ## STEP 1: DIAGNOSIS ### Error Received ``` TypeError: Cannot set properties of undefined (setting 'trackingEnabled') at Function [Work Order buttons]:143:37 ``` ### Root Cause Analysis **Node:** Work Order buttons **Line:** 143 **Problem:** `msg.payload` was **undefined** **Code that failed:** ```javascript msg._mode = "production-state"; msg.productionStarted = true; msg.machineOnline = true; // ❌ ERROR HERE - msg.payload doesn't exist! msg.payload.trackingEnabled = true; msg.payload.productionStarted = true; msg.payload.machineOnline = true; ``` **Why it failed:** The `msg` object in Node-RED doesn't automatically have a `payload` property. We were trying to set properties on an object that didn't exist, causing `Cannot set properties of undefined`. ### Secondary Issue: Mold Presets Handler Noise **Node:** Mold Presets Handler **Problem:** Logging warnings for every message it receives, including non-mold topics like `machineStatus`, `kpis`, `chartsData`, etc. **Debug output:** ``` "Unknown topic: selectMoldPreset" "Received: " "Unknown topic: " ``` **Why:** No filter to silently ignore messages not meant for this handler. --- ## STEP 2: THE FIX PLAN ### Fix 1: Initialize msg.payload Before Use **Architectural Decision:** - Initialize `msg.payload = {}` before setting properties - Set state flags at BOTH `msg` level AND `msg.payload` level for maximum compatibility - Preserve all existing global.set() calls (especially `kpiBuffer` clearing) **Compatibility Reasoning:** The "Back to UI" node reads: `msg.payload?.trackingEnabled ?? msg.trackingEnabled` This means it checks BOTH locations. By setting flags in both places, we ensure compatibility regardless of which path the message takes. ### Fix 2: Silent Ignore for Mold Presets Handler **Architectural Decision:** - Add early return for non-mold topics - Define explicit list of ignored topics - Only log messages for mold-related operations **Topics to silently ignore:** - `machineStatus` - Dashboard state updates - `kpis` - KPI calculations - `chartsData` - Graph data - `activeWorkOrder` - Work order updates - `workOrderCycle` - Cycle updates - `workOrdersList` - Work order list - `scrapPrompt` - Scrap entry prompts - `uploadStatus` - Upload confirmations - Empty string (`""`) --- ## STEP 3: IMPLEMENTATION ### Fix 1: Work Order buttons - "start" action **Before (Lines 136-146):** ```javascript msg._mode = "production-state"; msg.productionStarted = true; msg.machineOnline = true; // Send through output 2 to trigger KPI calculation // Add state info to the msg itself (will be sent to Calculate KPIs) msg.payload.trackingEnabled = true; // ❌ ERROR msg.productionStarted = true; msg.payload.productionStarted = true; msg.machineOnline = true; msg.payload.machineOnline = true; return [null, msg, null, null]; ``` **After (Lines 136-148):** ```javascript msg._mode = "production-state"; // Initialize payload object BEFORE setting properties msg.payload = msg.payload || {}; // Set state flags at both msg and msg.payload levels for compatibility msg.trackingEnabled = true; msg.productionStarted = true; msg.machineOnline = true; msg.payload.trackingEnabled = true; msg.payload.productionStarted = true; msg.payload.machineOnline = true; return [null, msg, null, null]; ``` **What was preserved:** ✅ `global.set("trackingEnabled", true)` ✅ `global.set("kpiBuffer", [])` ✅ `node.warn('[START] Cleared kpiBuffer for fresh production run')` ✅ All other global.set() calls ✅ Return statement structure ✅ Output routing --- ### Fix 2: Mold Presets Handler - Silent ignore **Before (Lines 1-4):** ```javascript const topic = msg.topic || ''; const payload = msg.payload || {}; // Log every incoming request node.warn(`Received: ${topic}`); ``` **After (Lines 1-19):** ```javascript const topic = msg.topic || ''; const payload = msg.payload || {}; // ===== IGNORE NON-MOLD TOPICS SILENTLY ===== // These are KPI/dashboard messages not meant for this handler const ignoredTopics = [ 'machineStatus', 'kpis', 'chartsData', 'activeWorkOrder', 'workOrderCycle', 'workOrdersList', 'scrapPrompt', 'uploadStatus' ]; if (ignoredTopics.includes(topic) || topic === '') { return null; // Silent ignore } // Log only mold-related requests node.warn(`Received: ${topic}`); ``` **What was preserved:** ✅ All mold preset handling logic ✅ Lock/dedupe mechanisms ✅ Database operations ✅ Error handling ✅ Existing functionality unchanged --- ## STEP 4: VERIFICATION ### Verification Checklist **Fix 1: Work Order buttons** - ✅ `msg.payload = msg.payload || {};` - Initialization added - ✅ `msg.trackingEnabled = true;` - Top-level flag set - ✅ `msg.payload.trackingEnabled = true;` - Nested flag set - ✅ `global.set("kpiBuffer", [])` - Buffer clearing preserved - ✅ `[START] Cleared kpiBuffer` - Warning message preserved - ✅ No duplicate flag settings - ✅ Clean code structure **Fix 2: Mold Presets Handler** - ✅ `ignoredTopics` array defined - ✅ `machineStatus` in ignore list - ✅ `kpis` in ignore list - ✅ `chartsData` in ignore list - ✅ Early return for ignored topics - ✅ Silent operation (no warnings for ignored topics) - ✅ Original logging preserved for mold topics --- ## EXPECTED BEHAVIOR AFTER DEPLOYMENT ### Before Fix ``` User clicks START ↓ ❌ Error: Cannot set properties of undefined (setting 'trackingEnabled') ❌ Production does not start ❌ Debug panel full of "Unknown topic" warnings ``` ### After Fix ``` User clicks START ↓ ✅ [START] Cleared kpiBuffer for fresh production run ✅ Production starts successfully ✅ trackingEnabled = true at global, msg, and msg.payload levels ✅ Button changes from START to STOP ✅ KPIs update continuously ✅ No "Unknown topic" warnings in debug panel ✅ Clean, noise-free debug output ``` --- ## TESTING INSTRUCTIONS 1. **Deploy the updated flows.json in Node-RED** 2. **Test Fix 1 - START button:** ``` - Load Home dashboard - Verify active work order exists - Click START button - Expected: No errors in debug panel - Expected: Message "[START] Cleared kpiBuffer for fresh production run" - Expected: Button changes to STOP - Expected: Production tracking begins ``` 3. **Test Fix 2 - Silent ignore:** ``` - Monitor debug panel - Navigate between dashboard tabs - Expected: No "Unknown topic" warnings for machineStatus, kpis, etc. - Expected: Only mold-related messages logged ``` 4. **Integration test:** ``` - Complete a full production cycle - Submit scrap - Verify KPIs update - Check graphs display data - Verify no errors throughout ``` --- ## ARCHITECTURAL NOTES ### Message Flow (Corrected) ``` START button click ↓ Work Order buttons (case "start") ├─ Sets: global.set("trackingEnabled", true) ├─ Clears: global.set("kpiBuffer", []) ├─ Initializes: msg.payload = {} ├─ Sets: msg.trackingEnabled = true ├─ Sets: msg.payload.trackingEnabled = true └─ Sends: [null, msg, null, null] → Output 2 ↓ Calculate KPIs (receives msg with _mode="production-state") ├─ Reads: global.get("trackingEnabled") ✅ ├─ Performs: KPI calculations └─ Sends: Output 1 → Refresh Trigger ↓ Refresh Trigger (sees _mode="production-state") └─ Routes: [null, msg] → Output 2 ↓ Back to UI (sees mode="production-state") ├─ Reads: msg.payload?.trackingEnabled ?? msg.trackingEnabled ✅ ├─ Creates: homeMsg with topic="machineStatus" └─ Sends: [null, homeMsg, null, null] ↓ link out → Home Template └─ Updates: scope.isProductionRunning = msg.payload.trackingEnabled ✅ ↓ Button displays: STOP ✅ ``` ### Why Both msg and msg.payload? The "Back to UI" node uses optional chaining: ```javascript trackingEnabled: msg.payload?.trackingEnabled ?? msg.trackingEnabled ?? false ``` This checks: 1. `msg.payload?.trackingEnabled` first (nested) 2. Falls back to `msg.trackingEnabled` (top-level) 3. Defaults to `false` By setting both, we ensure compatibility regardless of how the message is processed or which properties survive through the flow. --- ## FILES MODIFIED - `/home/mdares/.node-red/projects/Plastico/flows.json` - Work Order buttons node (ID: `9bbd4fade968036d`) - Mold Presets Handler node --- ## ROLLBACK INSTRUCTIONS If issues occur: ```bash cd /home/mdares/.node-red/projects/Plastico/ cp flows.json.backup_20251127_124628 flows.json # Restart Node-RED ``` --- **Status: SURGICAL FIX COMPLETE ✅** **Deployment: READY** **Risk Level: LOW** (Isolated changes, preservation verified)