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
- Run the installer from the true repo/package root: npx claude-mem@latest install from the directory containing .agents/plugins/marketplace.json.
- Verify the marker files exist: ls .agents/plugins/marketplace.json plugin/.codex-plugin/plugin.json in the root you passed.
- 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
- Run installers from the repo/package root, not subdirectories.
- Verify marker files exist before invoking any Codex installer.
- Ensure npm packaging (files field) includes .agents/ and plugin/.codex-plugin/.
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
- Could not locate a Codex marketplace root with…
- Codex marketplace is already registered from another…
- API key prompt cancelled — leaving existing configuration…
- claude-mem: could not read
- codex failed with exit code ` : ''}
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)