{"record":{"id":"8fa3bf0fd14f7f99","repo":"Yeachan-Heo/oh-my-codex","slug":"refusing-malformed-phase-in-entrypath","errorCode":null,"errorMessage":"Refusing malformed phase in ${entryPath}.","messagePattern":"Refusing malformed phase in (.+?)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cli/index.ts","lineNumber":8344,"sourceCode":"  if (!Array.isArray(value.active_skills)) {\n    throw new Error(`Refusing malformed active_skills in ${path}.`);\n  }\n  for (const [index, skill] of value.active_skills.entries()) {\n    const entryPath = `${path} active_skills[${index}]`;\n    if (!skill || typeof skill !== \"object\" || Array.isArray(skill)) {\n      throw new Error(`Refusing malformed active_skills entry ${index} in ${path}.`);\n    }\n    const entry = skill as Record<string, unknown>;\n    if (typeof entry.skill !== \"string\" || entry.skill.trim() === \"\") {\n      throw new Error(`Refusing malformed skill in ${entryPath}.`);\n    }\n    for (const field of [\"active\"] as const) {\n      if (Object.prototype.hasOwnProperty.call(entry, field) && typeof entry[field] !== \"boolean\") {\n        throw new Error(`Refusing malformed ${field} in ${entryPath}.`);\n      }\n    }\n    if (Object.prototype.hasOwnProperty.call(entry, \"phase\") && typeof entry.phase !== \"string\") {\n      throw new Error(`Refusing malformed phase in ${entryPath}.`);\n    }\n    for (const [field, fieldValue] of Object.entries(entry)) {\n      if (field.endsWith(\"_at\") && typeof fieldValue !== \"string\") {\n        throw new Error(`Refusing malformed ${field} in ${entryPath}.`);\n      }\n    }\n    assertExactSkillOwner(entry, authority, entryPath);\n  }\n}\n\ninterface CancellationTestFaults {\n  writeFailureMode?: string;\n  rollbackFailureMode?: string;\n}\n\nasync function cancelModes(\n  args: string[] = [],\n  options: { cwd?: string; testFaults?: CancellationTestFaults } = {},","sourceCodeStart":8326,"sourceCodeEnd":8362,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/cli/index.ts#L8326-L8362","documentation":"An active_skills entry may optionally carry a phase field, which must be a string when present. This error fires when phase exists but is not a string (number, boolean, object, null). phase typically labels a skill's lifecycle stage, so a non-string value signals schema corruption the library will not silently accept.","triggerScenarios":"A state entry like {\"skill\": \"x\", \"phase\": 2} or {\"skill\": \"x\", \"phase\": null}; the presence check passes but typeof entry.phase !== \"string\" is true.","commonSituations":"Schema changes between versions that made phase numeric; hand edits; migration scripts copying incompatible values into phase.","solutions":["Change phase to a string (e.g. 2 -> \"2\") or remove the field","If the value is meaningful, map it to the correct string phase label for your version","Retry the cancel command","Check release notes for phase schema changes after upgrading"],"exampleFix":"// before\n{ \"skill\": \"x\", \"phase\": 2 }\n// after\n{ \"skill\": \"x\", \"phase\": \"build\" }","handlingStrategy":"validation","validationCode":"function phasesValid(entries: Record<string, unknown>[]): boolean {\n  return entries.every((e) => !Object.prototype.hasOwnProperty.call(e, \"phase\") || typeof e.phase === \"string\");\n}","typeGuard":"function isOptionalString(v: unknown): v is string | undefined {\n  return v === undefined || typeof v === \"string\";\n}","tryCatchPattern":null,"preventionTips":["Keep phase as a labeled string","Check schema notes when upgrading versions that redefine phase"],"tags":["state-validation","cli","type-mismatch","cancel"],"backgroundTag":"schema-validation-failed","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}