odysseus-dev/odysseus · error · HTTPException
Failed to retrieve logs: {str(e)}
Error message
Failed to retrieve logs: {str(e)} What it means
Raised (HTTP 500) by the diagnostics logs endpoint (admin-gated) when anything inside the log-tail try block throws — most commonly an OSError while opening/reading the log file (missing file, permission denied, path is a directory) but the blanket `except Exception` also captures decode surprises. The original exception is logged as 'Diagnostics logs retrieval error' before the 500 is raised, with str(e) surfaced to the caller.
Source
Thrown at routes/diagnostics_routes.py:54
try:
log_file = os.path.join(DATA_DIR, "logs", "app.log")
if not os.path.exists(log_file):
return {"status": "success", "logs": []}
# Safe tail read of the log file (max 5MB via rotation)
with open(log_file, "r", encoding="utf-8", errors="ignore") as f:
lines = f.readlines()
tail_lines = lines[-limit:] if len(lines) > limit else lines
tail_lines = [line.rstrip('\r\n') for line in tail_lines]
return {
"status": "success",
"logs": tail_lines
}
except Exception as e:
logger.error(f"Diagnostics logs retrieval error: {e}")
raise HTTPException(500, f"Failed to retrieve logs: {str(e)}")
@router.get("/api/db/stats")
async def get_database_stats(request: Request) -> Dict[str, Any]:
require_admin(request)
try:
from core.database import get_detailed_stats
return get_detailed_stats()
except Exception as e:
logger.error(f"DB stats error: {e}")
raise HTTPException(500, "Failed to retrieve database statistics")
@router.get("/api/rag/stats")
async def get_rag_stats(request: Request) -> Dict[str, Any]:
require_admin(request)
if rag_available and rag_manager:
return rag_manager.get_stats()
return {"error": "RAG system not available"}
View on GitHub (pinned to f9235ebbf1)
Solutions
- Check the server console for the logged 'Diagnostics logs retrieval error: ...' line — it contains the exact OSError reason.
- Verify the log file exists and is readable by the server process user (ls -l + sudo -u <user> head <file>).
- If the file was rotated/renamed, point the diagnostics config at the current log path or restart so logging recreates it.
- For huge logs, tail the file (seek from end) instead of relying on readlines() over the whole file.
Example fix
// before
with open(log_file, 'r', encoding='utf-8', errors='ignore') as f:
lines = f.readlines()
// after (streaming tail, no full-file read)
import subprocess
tail = subprocess.run(['tail', '-n', str(limit), log_file], capture_output=True, text=True)
tail_lines = tail.stdout.splitlines() Defensive patterns
Strategy: try-catch
Validate before calling
# Pre-flight the log file is readable before requesting the tail
import os
if not os.path.isfile(log_file) or not os.access(log_file, os.R_OK):
skip_diagnostics('log file missing or unreadable') Try / catch
try { const r = await get('/api/logs?limit=200'); } catch (e) { if (e.status === 500 && /Failed to retrieve logs/.test(e.message)) { showBanner('Log file unavailable on server — see server console'); return []; } throw e; } Prevention
- Ensure the server process owns or can read the logs directory.
- Check the 'Diagnostics logs retrieval error' server log line for the root cause before changing anything.
When it happens
Trigger: GET of the logs tail endpoint when log_file points at a path that does not exist (logging not yet initialized / rotated away), is unreadable under the server's user, or when a filesystem error (NFS stall, disk issue) interrupts the read of a large log being read fully into memory via readlines().
Common situations: Fresh install where the log file has not been created yet; server runs under a different user than the one owning the logs directory; log rotated mid-request; extremely large log file causing memory pressure.
Related errors
- Failed to retrieve database statistics
- data.error || ('HTTP ' + (data.status || 500))
- model returned no rewritten text
- data.error || 'Failed to generate SSH key'
- HTTP ${res.status}
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/cdfd0b4bdbac6905.
Report an issue: GitHub.