Claude Code commited on
Commit
c652463
·
1 Parent(s): a05e0c7

Claude Code: [TASK] Investigate Cain's error logs and diagnose the actual issue. Chec

Browse files
app.py CHANGED
@@ -26,29 +26,43 @@ elif 'CAIN_STATUS_PATH' not in os.environ:
26
  os.environ['CAIN_STATUS_PATH'] = '/data/cain_status.json'
27
  print(f">>> CAIN: Set CAIN_STATUS_PATH (fallback) = {os.environ['CAIN_STATUS_PATH']}", flush=True)
28
 
29
- # CRITICAL: Immediately clean stale "unknown" error from primary status file
30
  # This must happen BEFORE any health checks read the status file
 
31
  _status_path = os.environ.get('CAIN_STATUS_PATH', '/data/cain_status.json')
32
- try:
33
- if Path(_status_path).exists():
34
- with open(_status_path, 'r') as f:
35
- _status_data = json.load(f)
36
- _error = _status_data.get('error')
37
- # Clean if error is a "null" string (unknown, none, null, empty)
38
- if isinstance(_error, str) and _error.strip().lower() in ('unknown', 'none', 'null', ''):
39
- _status_data['error'] = None
40
- _status_data['_cleaned_at'] = 'app_module_load'
41
- with open(_status_path, 'w') as f:
42
- json.dump(_status_data, f, indent=2)
43
- print(f">>> CAIN: Cleaned stale '{_error}' error from {_status_path}", flush=True)
44
- elif _error is None:
45
- print(f">>> CAIN: Status file OK (error=None)", flush=True)
46
- else:
47
- print(f">>> CAIN: Status file has error: {_error}", flush=True)
48
- else:
49
- print(f">>> CAIN: Status file does not exist yet: {_status_path}", flush=True)
50
- except Exception as e:
51
- print(f">>> CAIN: Could not clean status file: {e}", flush=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
  # CRITICAL: Create FastAPI app at TOP LEVEL, outside any try/except
54
  # This ensures the server ALWAYS starts, even if brain is broken
@@ -471,60 +485,27 @@ try:
471
  # Add explanatory note about error field semantics
472
  status_data["_note"] = "error=null means healthy - null or 'unknown' string are both treated as 'no error'"
473
 
474
- # Write to primary location (OPENCLAW_DATA_DIR)
475
- status_path = os.environ.get('CAIN_STATUS_PATH', '/data/cain_status.json')
476
- Path(status_path).parent.mkdir(parents=True, exist_ok=True)
477
- with open(status_path, 'w') as f:
478
- json.dump(status_data, f, indent=2)
479
- print(f">>> CAIN: Status file updated at {status_path}: stage=RUNNING_A2A_READY", flush=True)
480
-
481
- # Also write to brain_minimal's status file location for consistency
482
- # CRITICAL: Write to ALL possible locations to ensure "unknown" errors are cleared everywhere
483
- _script_dir = Path(os.path.abspath(os.path.dirname(__file__)))
484
- _possible_status_paths = [
485
- Path("/app/openclaw/.openclaw/agents/cain_status.json"), # Nested structure (Docker)
486
- Path("/app/.openclaw/agents/cain_status.json"), # Legacy flat structure
487
- Path("/app/cain_status.json"), # App root
488
- Path("/app/data/cain_status.json"), # App data subdirectory
489
- _script_dir / "openclaw" / ".openclaw" / "agents" / "cain_status.json",
490
- _script_dir / ".openclaw" / "agents" / "cain_status.json",
491
  ]
492
- for p in _possible_status_paths:
 
 
493
  try:
494
- # Create parent directory if it doesn't exist
495
- p.parent.mkdir(parents=True, exist_ok=True)
496
- # Check if file exists and has stale "unknown" error - ALWAYS clean it
497
- if p.exists():
498
- try:
499
- with open(p, 'r') as f:
500
- existing_data = json.load(f)
501
- # CRITICAL: Always overwrite if it has a stale "unknown" error, regardless of timestamp
502
- existing_error = existing_data.get('error')
503
- has_stale_error = (
504
- isinstance(existing_error, str) and
505
- existing_error.strip().lower() in ('unknown', 'none', 'null', '')
506
- )
507
- if has_stale_error:
508
- with open(p, 'w') as f:
509
- json.dump(status_data, f, indent=2)
510
- print(f">>> CAIN: Cleaned stale 'unknown' error at {p}", flush=True)
511
- # Also update if our status is newer
512
- elif status_data.get('last_updated', '') > existing_data.get('last_updated', ''):
513
- with open(p, 'w') as f:
514
- json.dump(status_data, f, indent=2)
515
- print(f">>> CAIN: Updated status at {p}", flush=True)
516
- except json.JSONDecodeError:
517
- # File exists but is corrupted - overwrite with clean data
518
- with open(p, 'w') as f:
519
- json.dump(status_data, f, indent=2)
520
- print(f">>> CAIN: Fixed corrupted status file at {p}", flush=True)
521
- else:
522
- # File doesn't exist - create it with clean data
523
- with open(p, 'w') as f:
524
- json.dump(status_data, f, indent=2)
525
- print(f">>> CAIN: Created new status file at {p}", flush=True)
526
  except Exception as e:
527
- print(f">>> CAIN WARNING: Could not write to {p}: {e}", flush=True)
 
 
528
  except Exception as e:
529
  print(f">>> CAIN WARNING: Could not update status file: {e}", flush=True)
530
 
 
26
  os.environ['CAIN_STATUS_PATH'] = '/data/cain_status.json'
27
  print(f">>> CAIN: Set CAIN_STATUS_PATH (fallback) = {os.environ['CAIN_STATUS_PATH']}", flush=True)
28
 
29
+ # CRITICAL: Immediately clean stale "unknown" error from ALL status file locations
30
  # This must happen BEFORE any health checks read the status file
31
+ # Fix for: Cain has RUNNING! Error: unknown - status files had stale error
32
  _status_path = os.environ.get('CAIN_STATUS_PATH', '/data/cain_status.json')
33
+ _all_status_paths = [
34
+ Path(_status_path), # Primary (OPENCLAW_DATA_DIR)
35
+ Path('/app/openclaw/.openclaw/agents/cain_status.json'), # Nested structure
36
+ Path('/app/.openclaw/agents/cain_status.json'), # Legacy flat structure
37
+ Path('/app/cain_status.json'), # App root
38
+ Path('/app/data/cain_status.json'), # App data subdirectory
39
+ Path(__file__).parent / 'memory' / 'cain_status.json', # Memory directory
40
+ ]
41
+
42
+ _cleaned_count = 0
43
+ for _sp in _all_status_paths:
44
+ try:
45
+ if _sp.exists():
46
+ with open(_sp, 'r') as f:
47
+ _status_data = json.load(f)
48
+ _error = _status_data.get('error')
49
+ # Clean if error is a "null" string (unknown, none, null, empty)
50
+ if isinstance(_error, str) and _error.strip().lower() in ('unknown', 'none', 'null', ''):
51
+ _status_data['error'] = None
52
+ _status_data['_cleaned_at'] = 'app_module_load_aggressive'
53
+ _status_data['_cleaned_path'] = str(_sp)
54
+ with open(_sp, 'w') as f:
55
+ json.dump(_status_data, f, indent=2)
56
+ _cleaned_count += 1
57
+ print(f">>> CAIN: Cleaned stale '{_error}' error from {_sp}", flush=True)
58
+ elif _error is None:
59
+ print(f">>> CAIN: Status OK: {_sp}", flush=True)
60
+ else:
61
+ print(f">>> CAIN: Status has real error at {_sp}: {_error}", flush=True)
62
+ except Exception as e:
63
+ print(f">>> CAIN: Could not clean {_sp}: {e}", flush=True)
64
+
65
+ print(f">>> CAIN: Cleaned {_cleaned_count} status file(s) at module load", flush=True)
66
 
67
  # CRITICAL: Create FastAPI app at TOP LEVEL, outside any try/except
68
  # This ensures the server ALWAYS starts, even if brain is broken
 
485
  # Add explanatory note about error field semantics
486
  status_data["_note"] = "error=null means healthy - null or 'unknown' string are both treated as 'no error'"
487
 
488
+ # Write to ALL possible locations to ensure consistency and prevent stale errors
489
+ all_status_paths = [
490
+ os.environ.get('CAIN_STATUS_PATH', '/data/cain_status.json'),
491
+ '/app/openclaw/.openclaw/agents/cain_status.json',
492
+ '/app/.openclaw/agents/cain_status.json',
493
+ '/app/cain_status.json',
494
+ '/app/data/cain_status.json',
495
+ os.path.join(os.path.dirname(__file__), 'memory', 'cain_status.json'),
 
 
 
 
 
 
 
 
 
496
  ]
497
+
498
+ written_count = 0
499
+ for status_path in all_status_paths:
500
  try:
501
+ Path(status_path).parent.mkdir(parents=True, exist_ok=True)
502
+ with open(status_path, 'w') as f:
503
+ json.dump(status_data, f, indent=2)
504
+ written_count += 1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
505
  except Exception as e:
506
+ print(f">>> CAIN WARNING: Could not write to {status_path}: {e}", flush=True)
507
+
508
+ print(f">>> CAIN: Status file written to {written_count} location(s): stage=RUNNING_A2A_READY, error=None", flush=True)
509
  except Exception as e:
510
  print(f">>> CAIN WARNING: Could not update status file: {e}", flush=True)
511
 
openclaw/.openclaw/agents/cain_status.json CHANGED
@@ -1,18 +1,18 @@
1
  {
2
  "current_state": "idle",
3
- "stage": "RUNNING_A2A_READY",
4
- "last_updated": "2026-03-16T16:30:00.000000+00:00",
5
  "agent": "cain",
6
  "error": null,
7
- "startup_checks": {
8
- "openclaw_imported": true,
9
- "brain_imported": true
10
- },
11
  "a2a": {
12
  "endpoint": "/a2a/jsonrpc",
13
  "enabled": true,
14
  "status": "ready",
15
  "brain_ready": true
16
  },
17
- "_note": "error=null means healthy - treated as 'no error'"
 
 
 
18
  }
 
1
  {
2
  "current_state": "idle",
3
+ "last_updated": "2026-03-16T20:24:46.319956+00:00",
 
4
  "agent": "cain",
5
  "error": null,
6
+ "_note": "error=null means healthy - treated as 'no error'",
7
+ "stage": "RUNNING_A2A_READY",
 
 
8
  "a2a": {
9
  "endpoint": "/a2a/jsonrpc",
10
  "enabled": true,
11
  "status": "ready",
12
  "brain_ready": true
13
  },
14
+ "startup_checks": {
15
+ "openclaw_imported": true,
16
+ "brain_imported": true
17
+ }
18
  }