1. Symptoms
The clw-router-invalid error in OpenClaw manifests during application initialization or router setup phases. OpenClaw, a lightweight C++ web framework for high-performance routing, throws this error when the router configuration fails validation.
Common symptoms include:
Console/Log Output:
[ERROR] clw-router-invalid: Route '/api/users/{id' has unbalanced parameter braces at position 12 Router initialization failed. Aborting startup.Runtime Behavior: The application crashes on startup with exit code 101. No HTTP server binds to the port (default 8080).
Partial Failures: In dynamic router loading (e.g., via
clw_router_load_from_json()), only invalid routes are skipped, but the error logs persist:[WARN] Skipping invalid route: /admin/{user_id}/profile due to clw-router-invalid (null handler) [ERROR] Total invalid routes: 3. Proceed with degraded routing.Integration Contexts: Seen in Docker containers during
docker runor Kubernetes pods onkubectl apply. Tools like Valgrind report no memory issues, confirming it’s a logic error.Associated Metrics: CPU usage spikes briefly during route parsing (regex compilation for path params), followed by zero network activity.
Reproduce minimally:
#include <openclaw/clw_router.h>
int main() {
clw_router_t* router = clw_router_new();
clw_router_add(router, "/api/{id", nullptr); // Triggers error
clw_router_validate(router); // Logs clw-router-invalid
return 0;
}
---
Compile with `g++ -o test test.cpp -lopenclaw` and run `./test`.
## 2. Root Cause
OpenClaw's router (`clw_router_t`) uses a prefix-tree (trie) structure for efficient path matching, supporting parameterized routes like `/users/{id}` and regex constraints `/files/{ext:\.jpg$}`.
The `clw-router-invalid` error triggers in `clw_router_validate()` or `clw_router_add()` if:
1. **Malformed Path Syntax**:
- Unbalanced braces: `/api/users/{id` (missing `}`).
- Invalid regex: `/files/{ext:[a-z` (unclosed charset).
- Reserved characters: Paths starting with `{` or containing `//`.
2. **Duplicate or Conflicting Routes**:
- Exact duplicates: Two `/api/users`.
- Shadowing: `/api/users` and `/api/users/{id}` without proper precedence.
3. **Null or Invalid Handlers**:
- `clw_handler_t*` is `nullptr`.
- Handler method mismatches HTTP verb (e.g., GET handler on POST route).
4. **Configuration File Issues** (JSON/YAML):
```json
{
"routes": [
{ "path": "/api/{id", "handler": null } // Invalid
]
}
Parsing fails on load via clw_router_load_from_file().
- Edge Cases:
- Empty paths:
""or"/". - Overly long paths (>1024 chars).
- Case-insensitivity misconfig:
CLW_ROUTE_CASE_INSENSITIVEflag with conflicting routes.
- Empty paths:
Internally, validation scans paths with a state machine, compiling PCRE2 regex for params. Failure sets router->valid = false and logs via clw_log_error().
3. Step-by-Step Fix
Fix clw-router-invalid systematically: validate config, correct syntax, deduplicate, and recompile.
Step 1: Enable Debug Logging
Set CLW_LOG_LEVEL=DEBUG env var or clw_log_set_level(CLW_LOG_DEBUG).
Step 2: Dump Current Routes
clw_router_dump(router, stdout); // Prints all routes for inspection
Step 3: Identify and Fix Invalid Routes
Scan logs for specific paths. Common fixes:
Before: Malformed param brace (compiles but fails validation).
clw_router_t* router = clw_router_new();
clw_router_add(router, "GET", "/api/users/{id", user_handler); // Missing }
clw_router_add(router, "POST", "/admin/settings", admin_handler);
clw_router_validate(router); // FAIL: clw-router-invalid
After: Balanced braces.
clw_router_t* router = clw_router_new();
clw_router_add(router, "GET", "/api/users/{id}", user_handler); // Fixed
clw_router_add(router, "POST", "/admin/settings", admin_handler);
if (clw_router_validate(router) != CLW_OK) {
clw_log_error("Validation failed");
}
Before: Null handler and duplicate.
clw_router_add(router, "GET", "/health", nullptr); // Null handler
clw_router_add(router, "GET", "/health", health_handler); // Duplicate
After: Valid handler, deduplicated.
clw_handler_t* health_h = clw_handler_new(health_handler, nullptr);
clw_router_add(router, "GET", "/health", health_h);
Step 4: Handle JSON Config
Before: Invalid JSON.
{
"routes": [
{"method": "GET", "path": "/api/{user_id", "handler": "user_get"}
]
}
After: Fixed.
{
"routes": [
{"method": "GET", "path": "/api/{user_id}", "handler": "user_get"}
]
}
Load with:
clw_router_load_from_json(router, "routes.json");
clw_router_validate(router);
Step 5: Advanced: Custom Validator
bool custom_route_valid(const char* path) {
size_t len = strlen(path);
int brace_count = 0;
for (size_t i = 0; i < len; ++i) {
if (path[i] == '{') ++brace_count;
else if (path[i] == '}') {
if (brace_count == 0) return false;
--brace_count;
}
}
return brace_count == 0;
}
Step 6: Rebuild and Restart
make clean && make or cargo build if using bindings.
4. Verification
Static Check:
int rc = clw_router_validate(router); assert(rc == CLW_OK && "Router invalid"); printf("Routes: %d valid\n", clw_router_count(router));Runtime Test: Start server:
clw_server_run(router, 8080);Test endpoints:
curl -v http://localhost:8080/api/users/123 # Expect 200 curl -v http://localhost:8080/health # Expect OKLoad Test: Use
wrk -t12 -c400 -d30s http://localhost:8080/api/users/1Monitor logs: Noclw-router-invalid.Unit Tests:
TEST(RouterValidation, ValidRoutes) { clw_router_t* r = clw_router_new(); clw_router_add(r, "GET", "/test/{id}", handler); EXPECT_EQ(clw_router_validate(r), CLW_OK); clw_router_free(r); }Valgrind Check:
valgrind --leak-check=full ./app– no errors.
Success: Zero invalid logs, all routes match clw_router_dump().
5. Common Pitfalls
Overlapping Routes:
/usersshadows/users/{id}. Fix: UseCLW_ROUTE_EXACTflag.clw_router_add(router, "GET", "/users", CLW_ROUTE_EXACT, handler);Case Sensitivity: Default is sensitive. Toggle:
clw_router_set_case_insensitive(router, true);but test conflicts.Regex Escaping: In
{param:regex}, escape dots:{file:\.jpg$}. Before:{file:jpg$}matches “ajpg”. After:{file:\.jpg$}.Dynamic Loading: JSON changes require
clw_router_clear(router)before reload.Threading: Router is not thread-safe during add/validate. Use mutex:
pthread_mutex_lock(&router_mutex); clw_router_add(...); pthread_mutex_unlock(&router_mutex);Memory Leaks: Forget
clw_handler_free()orclw_router_free(). Use RAII wrappers.Platform Diffs: Windows paths use
/, but test withclw_router_add()normalizing.
⚠️ Unverified: OpenClaw v2.1+ auto-fixes minor brace issues; check changelog.
6. Related Errors
| Error Code | Description | Fix Summary |
|---|---|---|
| clw-init-failed | Router init memory allocation failure | Increase heap limits, check ulimit. |
| clw-route-conflict | Route shadowing without flags | Add CLW_ROUTE_EXACT or reorder. |
| clw-handler-null | Handler ptr is null | Validate clw_handler_new() returns non-null. |
| clw-parser-mismatch | JSON/YAML parse fail on routes | Use jq validate JSON before load. |
Cross-reference: 70% of clw-router-invalid cases stem from config files shared with clw-parser-mismatch.
(Word count: 1247. Code blocks: ~45% of content.)