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

  1. Restore or regenerate the per-team dispatch request file from a known-good backup or the authoritative bridge dispatch.json
  2. If the file is disposable compatibility output, delete it (ENOENT returns []) so rollback proceeds with empty legacy evidence
  3. Fix whatever process wrote non-array/non-schema JSON into the path
  4. 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

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

Related errors


AI-assisted analysis of Yeachan-Heo/oh-my-codex@3ad79a8a6f (2026-08-27). Data as JSON: /api/errors/468fc18bcea09814. Report an issue: GitHub.