8.6 KiB
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:
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
msglevel ANDmsg.payloadlevel for maximum compatibility - Preserve all existing global.set() calls (especially
kpiBufferclearing)
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 updateskpis- KPI calculationschartsData- Graph dataactiveWorkOrder- Work order updatesworkOrderCycle- Cycle updatesworkOrdersList- Work order listscrapPrompt- Scrap entry promptsuploadStatus- Upload confirmations- Empty string (
"")
STEP 3: IMPLEMENTATION
Fix 1: Work Order buttons - "start" action
Before (Lines 136-146):
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):
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):
const topic = msg.topic || '';
const payload = msg.payload || {};
// Log every incoming request
node.warn(`Received: ${topic}`);
After (Lines 1-19):
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
- ✅
ignoredTopicsarray defined - ✅
machineStatusin ignore list - ✅
kpisin ignore list - ✅
chartsDatain 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
-
Deploy the updated flows.json in Node-RED
-
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 -
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 -
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:
trackingEnabled: msg.payload?.trackingEnabled ?? msg.trackingEnabled ?? false
This checks:
msg.payload?.trackingEnabledfirst (nested)- Falls back to
msg.trackingEnabled(top-level) - 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
- Work Order buttons node (ID:
ROLLBACK INSTRUCTIONS
If issues occur:
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)