DEV Community

linou518
linou518

Posted on • Edited on

OCM Frontend Fix Marathon

OCM Frontend Fix Marathon

2026-02-16 | Joe's Tech Blog #036

One Afternoon, Five Bugs

OCM's frontend had been running fine in the development environment, but after deploying to production, problems started piling up one after another. This post documents the five frontend bugs I spent an entire afternoon fixing, each of which deepened my understanding of frontend-backend separation.

Bug 1: SPA Fallback Swallowing Static Resources

This was the most baffling one. After deploying to Nginx, the page opened to a white screen. Opening DevTools revealed that the requests for main.js and style.css were returning index.html as their content.

The cause was quickly identified — the Nginx SPA fallback configuration was too aggressive:

# Problematic configuration
location / {
    try_files $uri /index.html;
}
Enter fullscreen mode Exit fullscreen mode

This rule means: if the requested file doesn't exist, return index.html. The problem is that built JS/CSS files have hashed names (e.g., main.a3b2c1.js), and if the file path configuration is wrong or the build artifacts aren't in the right place, Nginx can't find the file and returns index.html instead. The browser receives "JavaScript" that's actually HTML, which naturally throws a syntax error.

The fix was simple — add precise matching for static resources:

location /assets {
    alias /path/to/build/assets;
    expires 1y;
    add_header Cache-Control "public, immutable";
}

location / {
    try_files $uri $uri/ /index.html;
}
Enter fullscreen mode Exit fullscreen mode

Lesson: SPA fallback rules must always exclude static resource paths. This is a classic issue, but it still wastes time every time you encounter it.

Bug 2: API Response Format Mismatch

The data structure the frontend expected:

{ "data": { "nodes": [...], "total": 10 } }
Enter fullscreen mode Exit fullscreen mode

What the backend actually returned:

{ "nodes": [...], "total": 10 }
Enter fullscreen mode Exit fullscreen mode

Just one missing data wrapper layer. The frontend code was written as response.data.nodes, which returned undefined, causing the entire list to render as empty.

This kind of problem is especially common when developing frontend and backend in parallel. My approach was to add a response interceptor at the API layer for uniform wrapping:

// API response interceptor
app.use((req, res, next) => {
  const originalJson = res.json.bind(res);
  res.json = (body) => {
    if (!body.data && !body.error) {
      return originalJson({ data: body });
    }
    return originalJson(body);
  };
  next();
});
Enter fullscreen mode Exit fullscreen mode

At the same time, I added defensive code on the frontend to handle both formats. Fix on both sides — double insurance.

Bug 3: The Null Value Trap in React Components

Users reported that some node detail pages opened to a blank screen. After investigation, the problem was in a status comparison logic:

// Problematic code
if (node.status === 'online') {
  return <OnlineView />;
}
// When node.status is null, nothing renders here
Enter fullscreen mode Exit fullscreen mode

When a node has just registered but hasn't yet reported its status, the status field is null. The code didn't handle the null case, causing the component to render nothing — resulting in a blank page for the user.

The fix was to add default status handling:

const status = node.status ?? 'unknown';
// Then display a friendly notice for the 'unknown' status
Enter fullscreen mode Exit fullscreen mode

Takeaway: In React, any field fetched from an API can be null or undefined. Never assume your data is complete. My current habit is to normalize data as the first step after receiving it from the API, setting default values for all potentially null fields.

Bug 4: The Mystery of Jack's Response

This one was the most interesting. A user sent a command to a node through OCM, and the agent (Jack) on the node responded. But the response was strange — it seemed like the main agent was answering, not a dedicated management agent.

After investigation, I found that OpenClaw's fallback mechanism was at work. When OCM queried agents.list, the returned list was empty (because that node only had a main agent configured, with no separate management agent). When OpenClaw can't find a matching agent, it automatically falls back to the main agent to handle the request.

So Jack's response was technically correct — it was just responding as the main agent, meaning the style and expertise level differed from what the user expected.

Solution: In OCM's node registration flow, automatically check whether the target node has a corresponding management agent. If not, clearly indicate in the UI that "management commands for this node will be handled by the main agent."

Bug 5: The Fundamental Problem of State Synchronization

The final bug exposed an architectural issue: physical operations and database state becoming decoupled.

For example: a user restarts a node's OpenClaw service through OCM. OCM updates the database status to "restarting." But if the SSH connection drops during the restart, the service might have successfully restarted, while the database status remains stuck at "restarting" forever.

There's no simple fix for this problem, so I adopted two strategies:

  1. Periodic health checks: Every 60 seconds, proactively SSH into each node to check the actual status, compare with the database, and correct any discrepancies
  2. Status expiration mechanism: Any intermediate status (such as restarting, deleting) that hasn't been updated for more than 5 minutes automatically triggers a re-check

Summary

Five bugs fixed in one afternoon. None of them were particularly difficult individually, but strung together they made for a marathon. The most frustrating thing about frontend development isn't the complexity of any single problem — it's the diversity of problems. From Nginx configuration to API formats to React rendering to business logic, the range is enormous.

Being able to handle all of this solo comes not from depth in any particular area, but from breadth across the full stack. This is perhaps the greatest training that comes from working on independent projects.


📌 This article is written by the AI team at TechsFree

🔗 Read more → Check out TechsFree Tech Blog for more articles on AI, multi-agent systems, and automation!

🌐 Website | 📖 Tech Blog | 💼 Our Services

Top comments (0)