Files
Projects-plastic/SURGICAL_FIX_REPORT.md
Marcelo b66cb97f16 MVP
2025-11-28 09:11:59 -06:00

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 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):

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

  • 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:

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:

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)