{"record":{"id":"562c3f8e76854d91","repo":"Yeachan-Heo/oh-my-codex","slug":"refusing-cancellation-because-multiple-detached-ru","errorCode":null,"errorMessage":"Refusing cancellation because multiple detached run authorities match.","messagePattern":"Refusing cancellation because multiple detached run authorities match\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cli/index.ts","lineNumber":8165,"sourceCode":"        throw new Error(\"run directory escapes the authorized runs root\");\n      }\n      const stateDir = realpathSync(join(canonicalRunDir, \".omx\", \"state\"));\n      if (!isCanonicalPathWithin(canonicalRunDir, stateDir)) {\n        throw new Error(\"state directory escapes the authorized run directory\");\n      }\n      const session = JSON.parse(await readFile(join(stateDir, \"session.json\"), \"utf-8\")) as Record<string, unknown>;\n      if (session.session_id !== record.session_id) throw new Error(\"run session pointer changed\");\n      const sessionDir = realpathSync(join(stateDir, \"sessions\", record.session_id));\n      if (!isCanonicalPathWithin(stateDir, sessionDir)) {\n        throw new Error(\"session directory escapes the authorized state directory\");\n      }\n      candidates.push({ sessionDir, sessionId: record.session_id, record });\n    } catch (err) {\n      throw new Error(`Refusing cancellation because detached run authority is invalid: ${record.run_dir}.`, { cause: err });\n    }\n  }\n\n  if (candidates.length > 1) throw new Error(\"Refusing cancellation because multiple detached run authorities match.\");\n  if (candidates.length === 0) return null;\n  const [{ sessionDir, sessionId, record }] = candidates;\n  const refs: ModeStateFileRef[] = [];\n  const stateFiles = await readdir(sessionDir).catch(() => [] as string[]);\n  for (const file of stateFiles) {\n    if (!isModeStateFilename(file)) continue;\n    const path = join(sessionDir, file);\n    try {\n      const fileStat = lstatSync(path);\n      if (!fileStat.isFile() || fileStat.isSymbolicLink()) {\n        throw new Error(`Refusing cancellation through non-regular run state target: ${path}.`);\n      }\n      const canonicalFile = realpathSync(path);\n      if (!isCanonicalPathWithin(sessionDir, canonicalFile)) {\n        throw new Error(`Refusing cancellation outside authorized run session: ${path}.`);\n      }\n      refs.push({\n        mode: file.slice(0, -\"-state.json\".length),","sourceCodeStart":8147,"sourceCodeEnd":8183,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/cli/index.ts#L8147-L8183","documentation":"More than one detached run authority record matched the cancellation target (same cwd/context), which is ambiguous, so the CLI refuses to cancel rather than pick arbitrarily.","triggerScenarios":"Two active records both canonicalize to the same working directory and pass authority validation, producing candidates.length > 1.","commonSituations":"Launching detached sessions twice from the same repo, or stale active records accumulating after crashes (records not cleaned on exit).","solutions":["Cancel one session at a time by its explicit session id rather than by directory","Remove the stale/finished active record(s) leaving only the live one","Check for orphaned records after crashes and prune them"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const matches = records.filter(r => realpathSync(resolve(r.run_dir)) !== null /* + authority checks */);\nif (matches.length > 1) throw new Error('ambiguous: cancel by explicit session id');","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Cancel by session id, not by directory","Prune finished active records","Avoid launching duplicate detached sessions for one cwd"],"tags":["ambiguity","cancellation","state-management"],"backgroundTag":"ambiguous-target-state","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}