{"record":{"id":"1b4a92b0655c51c2","repo":"diegosouzapw/OmniRoute","slug":"detail","errorCode":null,"errorMessage":"detail","messagePattern":"detail","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/app/(dashboard)/dashboard/settings/components/RedisLauncherPanel.tsx","lineNumber":32,"sourceCode":"  detail?: string;\n};\n\nasync function apiCall(endpoint: string, options: RequestInit = {}) {\n  const res = await fetch(`/api/local/redis${endpoint}`, {\n    method: options.method || \"GET\",\n    headers: { \"Content-Type\": \"application/json\" },\n    body: options.body,\n    cache: \"no-store\",\n  });\n  if (!res.ok) {\n    let detail = `HTTP ${res.status}`;\n    try {\n      const json = await res.json();\n      if (json?.error) detail = json.error;\n    } catch {\n      // ignore\n    }\n    throw new Error(detail);\n  }\n  return res.json();\n}\n\n/**\n * Compact 1-click Redis control. Sits inside the resilience settings tab and\n * shells out to the same logic exposed via the `omniroute redis` CLI command.\n * The actual container management is delegated to the server-side endpoint\n * at /api/local/redis/* so the browser never executes podman/docker directly.\n */\nexport default function RedisLauncherPanel() {\n  const t = useTranslations(\"settings\");\n  const [state, setState] = useState<LaunchState>(\"idle\");\n  const [status, setStatus] = useState<Status | null>(null);\n  const [error, setError] = useState<string | null>(null);\n\n  async function refresh() {\n    setState(\"checking\");","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/diegosouzapw/OmniRoute/blob/a179ffed5bb2e0b883b9ae7214ce8717b2a94c4d/src/app/(dashboard)/dashboard/settings/components/RedisLauncherPanel.tsx#L14-L50","documentation":"Shared apiCall() guard in the Redis launcher panel: every /api/local/redis<endpoint> request that returns non-ok builds a 'detail' message — the JSON body's error field when parseable, otherwise the raw 'HTTP <status>' sentinel — and throws it. The thrown value simply reports why the Redis control action (start/stop/status/config) was rejected; it carries no Redis-specific semantics of its own.","triggerScenarios":"Thrown at src/app/(dashboard)/dashboard/settings/components/RedisLauncherPanel.tsx:32 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":["Check the Redis service status card: the control panel calls /api/local/redis endpoints, so verify the embedded Redis service is actually running before retrying the operation.","Inspect the error detail: apiCall prefers the JSON body's error field over the raw 'HTTP <status>' string, which usually names the failing action (start/stop/config) directly.","If the status is 5xx, check server logs for the Redis child process failing to spawn (port conflict, missing binary, permission issue on the data directory).","Retry the action after the service settles — start/stop races can produce transient 409/503 responses from the local Redis controller."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"a179ffed5bb2e0b883b9ae7214ce8717b2a94c4d","analyzedAt":"2026-08-25T18:35:09.898Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}