Yeachan-Heo/oh-my-codex · error · Error

Refusing malformed active_skills in ${path}.

Error message

Refusing malformed active_skills in ${path}.

What it means

This error is thrown by the session-cancellation state validator when a loaded state document contains an active_skills property that is not an array. The CLI refuses to operate on state files whose shape it cannot safely interpret, treating a malformed active_skills collection as corruption rather than best-effort parsing it. It exists to prevent cancellation logic from mutating partially understood state.

Source

Thrown at src/cli/index.ts:8327

  if (Object.prototype.hasOwnProperty.call(value, "owner_codex_session_id")) {
    const rawOwner = value.owner_codex_session_id;
    const blankOwner = typeof rawOwner === "string" && rawOwner.trim() === "";
    const owner = normalizeSessionId(rawOwner);
    if (!blankOwner && (!owner || (!allowStaleTopCodexOwner && owner !== authority.nativeSessionId))) {
      throw new Error(`Refusing contradictory owner_codex_session_id in ${path}.`);
    }
  }
}


function assertCompatibleNestedSkillOwners(
  value: Record<string, unknown>,
  authority: ExactSessionCancellationAuthority,
  path: string,
): void {
  if (!Object.prototype.hasOwnProperty.call(value, "active_skills")) return;
  if (!Array.isArray(value.active_skills)) {
    throw new Error(`Refusing malformed active_skills in ${path}.`);
  }
  for (const [index, skill] of value.active_skills.entries()) {
    const entryPath = `${path} active_skills[${index}]`;
    if (!skill || typeof skill !== "object" || Array.isArray(skill)) {
      throw new Error(`Refusing malformed active_skills entry ${index} in ${path}.`);
    }
    const entry = skill as Record<string, unknown>;
    if (typeof entry.skill !== "string" || entry.skill.trim() === "") {
      throw new Error(`Refusing malformed skill in ${entryPath}.`);
    }
    for (const field of ["active"] as const) {
      if (Object.prototype.hasOwnProperty.call(entry, field) && typeof entry[field] !== "boolean") {
        throw new Error(`Refusing malformed ${field} in ${entryPath}.`);
      }
    }
    if (Object.prototype.hasOwnProperty.call(entry, "phase") && typeof entry.phase !== "string") {
      throw new Error(`Refusing malformed phase in ${entryPath}.`);
    }

View on GitHub (pinned to 3ad79a8a6f)

Solutions

  1. Inspect the state file named in ${path} and check the active_skills field's type
  2. Fix active_skills to be an array of skill entries, or remove the property entirely
  3. If the file was written by a different tool version, regenerate or re-sync the state via the owning command
  4. Restore from a backup state file if the content is unrecoverable

Example fix

// before
"active_skills": { "build": true }
// after
"active_skills": [{ "skill": "build", "active": true }]
Defensive patterns

Strategy: validation

Validate before calling

import { readFileSync } from "node:fs";
function stateHasValidActiveSkills(path: string): boolean {
  const parsed = JSON.parse(readFileSync(path, "utf-8"));
  if (!Object.prototype.hasOwnProperty.call(parsed, "active_skills")) return true;
  return Array.isArray(parsed.active_skills);
}

Type guard

function hasWellFormedActiveSkills(v: unknown): v is { active_skills?: unknown[] } {
  if (!v || typeof v !== "object" || Array.isArray(v)) return false;
  const rec = v as Record<string, unknown>;
  return !Object.prototype.hasOwnProperty.call(rec, "active_skills") || Array.isArray(rec.active_skills);
}

Prevention

When it happens

Trigger: Calling the cancel command on a workspace whose state JSON has active_skills set to an object, string, number, or null (e.g. {"active_skills": {"skill": "x"}} or {"active_skills": null}). Also triggered if an external tool or hand-edit wrote the state file with a non-array value.

Common situations: Hand-edited state files; older/newer CLI versions that serialized active_skills differently; external scripts or editors that rewrote state JSON and changed the type; corrupted or partially-written state files after a crash.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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