thedotmack/claude-mem · error

Codex marketplace root

Error message

Codex marketplace root ${resolved} is missing required files: ${missing.join(', ')}

What it means

assertCodexMarketplaceRoot() validates that a candidate Codex marketplace root directory contains all required marker files (.agents/plugins/marketplace.json and plugin/.codex-plugin/plugin.json). If missingMarketplaceFiles() returns any entries, it throws with the resolved root and the list of missing files, because installing the Codex plugin from an incomplete root would fail downstream.

Solutions

  1. Run the installer from the true repo/package root: npx claude-mem@latest install from the directory containing .agents/plugins/marketplace.json.
  2. Verify the marker files exist: ls .agents/plugins/marketplace.json plugin/.codex-plugin/plugin.json in the root you passed.
  3. If installing from an npm package, ensure the package includes .agents/ and plugin/.codex-plugin/ (check the files field in package.json) or reinstall a complete release.

Example fix

// before: invoked from a subdirectory without markers
cd plugin/src && npx claude-mem@latest install
// Error: Codex marketplace root ... is missing required files: .agents/plugins/marketplace.json

// after: run from the repo root that has both marker files
cd /path/to/claude-mem && npx claude-mem@latest install
Defensive patterns

Strategy: validation

Validate before calling

import { existsSync } from 'fs';
import path from 'path';
const root = path.resolve(preferredRoot);
const required = ['.agents/plugins/marketplace.json', 'plugin/.codex-plugin/plugin.json'];
const missing = required.filter((f) => !existsSync(path.join(root, f)));
if (missing.length > 0) {
  throw new Error(`Run from the real marketplace root; missing: ${missing.join(', ')}`);
}

Prevention

When it happens

Trigger: resolvePluginMarketplaceRoot(preferredRoot) is called with a preferredRoot that exists but lacks one or both required files; assertCodexMarketplaceRoot resolves it and finds missing marker files.

Common situations: Pointing the installer at a checkout of only part of the repo (e.g. a subdirectory or shallow copy without .agents/ or plugin/.codex-plugin/); running from a packaged npm tarball that excludes dot-directories (.npmignore/files list omits .agents/); a partially cloned repo where dotfiles were skipped.

Understand the failure class

Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.

Related errors


AI-assisted analysis of thedotmack/claude-mem@d8bc9755e7 (2026-09-17). Data as JSON: /api/errors/268fd7e9b8b6f8d0. Report an issue: GitHub.

Appendix: source

Thrown at src/services/integrations/CodexCliInstaller.ts:103

  while (true) {
    if (existsSync(path.join(current, '.agents', 'plugins', 'marketplace.json'))) {
      return current;
    }
    const parent = path.dirname(current);
    if (parent === current) return null;
    current = parent;
  }
}

function missingMarketplaceFiles(root: string): string[] {
  return REQUIRED_MARKETPLACE_FILES.filter((entry) => !existsSync(path.join(root, entry)));
}

function assertCodexMarketplaceRoot(root: string): string {
  const resolved = path.resolve(root);
  const missing = missingMarketplaceFiles(resolved);
  if (missing.length > 0) {
    throw new Error(`Codex marketplace root ${resolved} is missing required files: ${missing.join(', ')}`);
  }
  return resolved;
}

function resolvePluginMarketplaceRoot(preferredRoot?: string): string {
  if (preferredRoot) {
    return assertCodexMarketplaceRoot(preferredRoot);
  }

  const candidates = [
    process.env.CLAUDE_PLUGIN_ROOT,
    process.env.PLUGIN_ROOT,
    process.cwd(),
    path.dirname(fileURLToPath(import.meta.url)),
  ].filter((value): value is string => Boolean(value));

  for (const candidate of candidates) {
    const resolved = findAncestorWithCodexMarketplace(candidate);

View on GitHub (pinned to d8bc9755e7)