{"record":{"id":"ec8a6c7323f0073a","repo":"Yeachan-Heo/oh-my-codex","slug":"refusing-malformed-skill-in-entrypath","errorCode":null,"errorMessage":"Refusing malformed skill in ${entryPath}.","messagePattern":"Refusing malformed skill in (.+?)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cli/index.ts","lineNumber":8336,"sourceCode":"\n\nfunction assertCompatibleNestedSkillOwners(\n  value: Record<string, unknown>,\n  authority: ExactSessionCancellationAuthority,\n  path: string,\n): void {\n  if (!Object.prototype.hasOwnProperty.call(value, \"active_skills\")) return;\n  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","sourceCodeStart":8318,"sourceCodeEnd":8354,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/cli/index.ts#L8318-L8354","documentation":"Each active_skills entry must carry a non-empty string skill identifier; this error fires when entry.skill is missing, not a string, or an empty/whitespace-only string. The skill name is the key cancellation logic uses to match and update entries, so it must be present and well-formed. The library refuses rather than guessing a default.","triggerScenarios":"An entry like {}, {\"skill\": 42}, {\"skill\": \"\"}, or {\"skill\": \"   \"} inside active_skills in the state file being cancelled against.","commonSituations":"Partial manual edits that added an entry without a skill name; schema drift between CLI versions; tools that emit empty placeholders for unused skill slots.","solutions":["Locate the entry at the reported active_skills index in the state file","Set skill to a non-empty trimmed string or remove the entry","Save and retry the cancel command","Validate state files with a schema check after external tooling writes them"],"exampleFix":"// before\n{ \"active\": true }\n// after\n{ \"skill\": \"deploy\", \"active\": true }","handlingStrategy":"validation","validationCode":"function skillNamesValid(entries: Record<string, unknown>[]): boolean {\n  return entries.every((e) => typeof e.skill === \"string\" && e.skill.trim() !== \"\");\n}","typeGuard":"function isNamedSkillEntry(v: unknown): v is { skill: string } & Record<string, unknown> {\n  return isSkillEntry(v) && typeof (v as Record<string, unknown>).skill === \"string\" && (v as { skill: string }).skill.trim() !== \"\";\n}","tryCatchPattern":null,"preventionTips":["Always include a non-empty skill name when adding entries","Trim and assert skill names in any script that writes state"],"tags":["state-validation","cli","required-field","cancel"],"backgroundTag":"schema-validation-failed","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}