{"record":{"id":"268fd7e9b8b6f8d0","repo":"thedotmack/claude-mem","slug":"codex-marketplace-root-resolved-is-missing-requ","errorCode":null,"errorMessage":"Codex marketplace root ${resolved} is missing required files: ${missing.join(', ')}","messagePattern":"Codex marketplace root (.+?) is missing required files: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/services/integrations/CodexCliInstaller.ts","lineNumber":65,"sourceCode":"  while (true) {\n    if (existsSync(path.join(current, '.agents', 'plugins', 'marketplace.json'))) {\n      return current;\n    }\n    const parent = path.dirname(current);\n    if (parent === current) return null;\n    current = parent;\n  }\n}\n\nfunction missingMarketplaceFiles(root: string): string[] {\n  return REQUIRED_MARKETPLACE_FILES.filter((entry) => !existsSync(path.join(root, entry)));\n}\n\nfunction assertCodexMarketplaceRoot(root: string): string {\n  const resolved = path.resolve(root);\n  const missing = missingMarketplaceFiles(resolved);\n  if (missing.length > 0) {\n    throw new Error(`Codex marketplace root ${resolved} is missing required files: ${missing.join(', ')}`);\n  }\n  return resolved;\n}\n\nfunction resolvePluginMarketplaceRoot(preferredRoot?: string): string {\n  if (preferredRoot) {\n    return assertCodexMarketplaceRoot(preferredRoot);\n  }\n\n  const candidates = [\n    process.env.CLAUDE_PLUGIN_ROOT,\n    process.env.PLUGIN_ROOT,\n    process.cwd(),\n    path.dirname(fileURLToPath(import.meta.url)),\n  ].filter((value): value is string => Boolean(value));\n\n  for (const candidate of candidates) {\n    const resolved = findAncestorWithCodexMarketplace(candidate);","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/thedotmack/claude-mem/blob/d768ba364302d12b76e69e4f021f0bb1d2d50ed6/src/services/integrations/CodexCliInstaller.ts#L47-L83","documentation":"assertCodexMarketplaceRoot() validates that a candidate directory contains every entry in REQUIRED_MARKETPLACE_FILES (.agents/plugins/marketplace.json, plugin/.codex-plugin/plugin.json, plugin/.mcp.json, plugin/hooks/codex-hooks.json, plugin/skills/mem-search/SKILL.md). When an explicit preferredRoot is supplied and any file is missing, it throws listing the gaps rather than registering a half-built marketplace with Codex.","triggerScenarios":"resolvePluginMarketplaceRoot is called with an explicit preferredRoot (or a candidate resolves) but that directory lacks one or more of the required layout files. Triggered during the Codex install path when CLAUDE_PLUGIN_ROOT/PLUGIN_ROOT/cwd points at an incomplete checkout.","commonSituations":"Running the Codex installer from a shallow/partial clone; a build step that copies only some plugin artifacts; pointing CLAUDE_PLUGIN_ROOT at a staging dir missing hooks or skills; an interrupted build-and-sync left the tree half-populated.","solutions":["Re-run the full build/install (`npm run build-and-sync` or `npx claude-mem@latest install`) so all required files are generated.","Inspect the missing files listed in the message and ensure each exists under the resolved root.","If you passed a custom root via CLAUDE_PLUGIN_ROOT, point it at a complete plugin tree or unset it to use auto-detection.","Run the install from the repo/package root as the message implies."],"exampleFix":"# before — root missing plugin/.mcp.json\nnpx claude-mem@latest install --codex\n# -> missing required files: plugin/.mcp.json\n\n# after — regenerate the full layout\nnpm run build-and-sync\nnpx claude-mem@latest install --codex","handlingStrategy":"validation","validationCode":"import { existsSync } from 'fs';\nimport path from 'path';\n\nconst REQUIRED = [\n  '.agents/plugins/marketplace.json',\n  'plugin/.codex-plugin/plugin.json',\n  'plugin/.mcp.json',\n  'plugin/hooks/codex-hooks.json',\n  'plugin/skills/mem-search/SKILL.md',\n];\n\nfunction marketplaceRootComplete(root: string): boolean {\n  return REQUIRED.every((rel) => existsSync(path.join(root, rel)));\n}","typeGuard":"function isMissingMarketplaceFilesError(e: unknown): boolean {\n  return e instanceof Error && /Codex marketplace root .* is missing required files/i.test(e.message);\n}","tryCatchPattern":"try {\n  assertCodexMarketplaceRoot(root);\n} catch (e) {\n  if (e instanceof Error && /missing required files/.test(e.message)) {\n    console.error(e.message);\n    console.error('Run `npm run build-and-sync` (or npx claude-mem@latest install) and retry.');\n    process.exit(1);\n  }\n  throw e;\n}","preventionTips":["Generate the full plugin layout before registering it with Codex.","Point CLAUDE_PLUGIN_ROOT only at complete trees.","Add a CI check that asserts all REQUIRED_MARKETPLACE_FILES exist post-build."],"tags":["installer","codex","filesystem","plugin-layout","validation"],"backgroundTag":null,"analyzedSha":"d768ba364302d12b76e69e4f021f0bb1d2d50ed6","analyzedAt":"2026-08-12T23:52:55.241Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}