Yeachan-Heo/oh-my-codex · error · Error
legacy dispatch rollback evidence is malformed or unrecogniz
Error message
legacy dispatch rollback evidence is malformed or unrecognized
What it means
Thrown when the legacy per-team dispatch request file exists but is not a JSON array, or any entry fails strict validation as a rollback-safe TeamDispatchRequest. The file is read during rollback of dispatch requests to discover which legacy request IDs were issued for the workers being removed.
Source
Thrown at src/team/state.ts:2096
&& request.team_name === teamName
&& typeof request.to_worker === 'string'
&& request.to_worker.length > 0
&& typeof request.trigger_message === 'string'
&& ['hook_preferred_with_fallback', 'transport_direct', 'prompt_stdin'].includes(String(request.transport_preference))
&& typeof request.fallback_allowed === 'boolean'
&& ['pending', 'notified', 'delivered', 'failed'].includes(String(request.status))
&& typeof request.attempt_count === 'number'
&& Number.isFinite(request.attempt_count)
&& typeof request.created_at === 'string'
&& typeof request.updated_at === 'string';
}
async function readLegacyDispatchRequestsForRollback(teamName: string, cwd: string): Promise<TeamDispatchRequest[]> {
const path = dispatchRequestsPath(teamName, cwd);
try {
const raw = JSON.parse(await readFile(path, 'utf8')) as unknown;
if (!Array.isArray(raw) || raw.some((entry) => !isStrictLegacyDispatchRequestForRollback(entry, teamName))) {
throw new Error('legacy dispatch rollback evidence is malformed or unrecognized');
}
return raw as TeamDispatchRequest[];
} catch (error) {
if ((error as NodeJS.ErrnoException).code === 'ENOENT') return [];
throw error;
}
}
async function writeDispatchRequests(teamName: string, requests: TeamDispatchRequest[], cwd: string): Promise<void> {
await writeAtomic(dispatchRequestsPath(teamName, cwd), JSON.stringify(requests, null, 2));
await writeBridgeDispatchCompat(teamName, requests, cwd);
}
function serializeDispatchRequestToBridgeRecord(request: TeamDispatchRequest): DispatchRecord {
return {
request_id: request.request_id,
target: request.to_worker,
status: request.status,View on GitHub (pinned to 3ad79a8a6f)
Solutions
- Restore or regenerate the per-team dispatch request file from a known-good backup or the authoritative bridge dispatch.json
- If the file is disposable compatibility output, delete it (ENOENT returns []) so rollback proceeds with empty legacy evidence
- Fix whatever process wrote non-array/non-schema JSON into the path
- Check for concurrent unserialized writers to dispatchRequestsPath(teamName, cwd)
Example fix
// before: corrupted file causes throw
// after: allow rollback to proceed with no legacy evidence
try {
await rollbackDispatch(names);
} catch (e) {
if (String(e.message).startsWith('legacy dispatch rollback evidence is malformed')) {
await rm(dispatchRequestsPath(team, cwd), { force: true });
await rollbackDispatch(names);
} else throw e;
} Defensive patterns
Strategy: fallback
Validate before calling
import { readFileSync } from 'node:fs';
function legacyDispatchFileOk(path: string): boolean {
try {
const raw = JSON.parse(readFileSync(path, 'utf8'));
return Array.isArray(raw);
} catch { return false; }
} Type guard
function isLegacyDispatchFileViable(path: string): boolean {
return legacyDispatchFileOk(path);
} Try / catch
catch (e) { if ((e as Error).message.includes('legacy dispatch rollback evidence')) { /* reset/regenerate legacy file, retry rollback once */ } else throw e; } Prevention
- Never hand-edit the legacy dispatch file
- Keep a single serialized writer per team's dispatch file
- Treat the file as regenerable compatibility output
When it happens
Trigger: Calling the team membership rollback path (removing workers / rolling back dispatch) when .team/<team>/dispatch-requests.json is corrupted, hand-edited, truncated, or contains entries with missing/foreign team_name fields.
Common situations: Concurrent writers corrupted the legacy file; a migration wrote a different schema; partial write due to crash; manual editing of the file.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- authoritative_dispatch_rollback_discovery_failed:${[...names
- --handoff-json must resolve to a JSON object.
- preLaunch ${completion.operation} failed
- detached leader authority missing before rollback
- Refusing cancellation because state content changed: ${chang
AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27).
Data as JSON: /api/errors/468fc18bcea09814.
Report an issue: GitHub.