{"record":{"id":"52bd2c8ebfcf83d5","repo":"Yeachan-Heo/oh-my-codex","slug":"status-must-be-one-of-running-blocked-failed-co","errorCode":null,"errorMessage":"status must be one of running, blocked, failed, complete","messagePattern":"status must be one of running, blocked, failed, complete","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/mcp/hermes-bridge.ts","lineNumber":654,"sourceCode":"    } finally {\n      await handle.close();\n    }\n  } catch (error) {\n    return failure(\"invalid_input\", error instanceof Error ? error.message : String(error));\n  }\n}\n\nexport async function hermesReportStatus(\n  args: Record<string, unknown>,\n  deps: HermesBridgeDeps = {},\n): Promise<HermesBridgeResult<{ path: string; report: Record<string, unknown> }>> {\n  try {\n    requireMutation(args);\n    const cwd = resolveWorkingDirectoryForState(normalizeString(args.workingDirectory, \"workingDirectory\"));\n    const sessionId = validateSessionId(normalizeString(args.session_id, \"session_id\"));\n    const status = normalizeString(args.status, \"status\", { required: true })!;\n    if (![\"running\", \"blocked\", \"failed\", \"complete\"].includes(status)) {\n      throw new Error(\"status must be one of running, blocked, failed, complete\");\n    }\n    const summary = normalizeString(args.summary, \"summary\");\n    const prUrl = normalizeString(args.pr_url, \"pr_url\");\n    const blocker = normalizeString(args.blocker, \"blocker\");\n    const report = {\n      status,\n      updated_at: (deps.now ?? (() => new Date()))().toISOString(),\n      ...(summary ? { summary } : {}),\n      ...(prUrl ? { pr_url: prUrl } : {}),\n      ...(blocker ? { blocker } : {}),\n    };\n    const stateDir = sessionId ? join(getBaseStateDir(cwd), \"sessions\", sessionId) : getBaseStateDir(cwd);\n    const path = join(stateDir, \"hermes-coordination.json\");\n    await mkdir(dirname(path), { recursive: true });\n    await writeFile(path, JSON.stringify(report, null, 2) + \"\\n\");\n    return jsonResult({ path, report });\n  } catch (error) {\n    const message = error instanceof Error ? error.message : String(error);","sourceCodeStart":636,"sourceCodeEnd":672,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/mcp/hermes-bridge.ts#L636-L672","documentation":"Thrown by the session-report mutation handler when args.status is not one of the four allowed lifecycle values: running, blocked, failed, complete. Status is required and strictly enumerated so downstream state stays consistent.","triggerScenarios":"Calling the report tool with status=\"done\", status=\"success\", status=\"completed\" (instead of complete), or an empty string.","commonSituations":"LLM-generated tool calls inventing synonyms; clients copying status vocabularies from other systems (succeeded/canceled); locale differences.","solutions":["Use exactly one of: running, blocked, failed, complete","Map your internal status enum to these four values before calling","Validate status against the list before invoking the tool"],"exampleFix":"// before\nawait report({ status: \"done\", summary: \"...\" });\n// after\nawait report({ status: \"complete\", summary: \"...\" });","handlingStrategy":"validation","validationCode":"const STATUSES = ['running', 'blocked', 'failed', 'complete'] as const;\nif (!STATUSES.includes(status)) throw new TypeError(`status must be one of ${STATUSES.join(', ')}`);","typeGuard":"type Status = typeof STATUSES[number];\nfunction isStatus(v: unknown): v is Status { return typeof v === 'string' && (STATUSES as readonly string[]).includes(v); }","tryCatchPattern":null,"preventionTips":["Model status as a closed union type in your client","Map internal enums to the four allowed words explicitly"],"tags":["enum-validation","mcp","session"],"backgroundTag":"enum-value-invalid","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}