thedotmack/claude-mem · error
Could not locate a Codex marketplace root with…
Error message
Could not locate a Codex marketplace root with .agents/plugins/marketplace.json and plugin/.codex-plugin/plugin.json. Run npx claude-mem@latest install from the package or repo root.
What it means
resolvePluginMarketplaceRoot() walks a list of candidate directories (and their ancestors) looking for one that has both .agents/plugins/marketplace.json and plugin/.codex-plugin/plugin.json. When no candidate resolves to a complete marketplace root, it throws with instructions to run the installer from the package or repo root. This is the fallback error when the Codex install cannot self-locate its marketplace.
Solutions
- cd into the claude-mem package or repo root (the one containing .agents/plugins/marketplace.json) and run npx claude-mem@latest install.
- Verify both markers exist: ls .agents/plugins/marketplace.json plugin/.codex-plugin/plugin.json; create/restore them from a complete checkout if absent.
- Pass an explicit preferredRoot pointing at the correct marketplace root so the ancestor search is not needed.
Example fix
// before: run from an unrelated directory npx claude-mem@latest install // Error: Could not locate a Codex marketplace root... // after: run from the repo root with the marker files cd ~/code/claude-mem && npx claude-mem@latest install
Defensive patterns
Strategy: validation
Validate before calling
import { existsSync } from 'fs';
import path from 'path';
function findMarketplaceRoot(start: string): string | null {
let dir = path.resolve(start);
while (true) {
if (existsSync(path.join(dir, '.agents/plugins/marketplace.json')) &&
existsSync(path.join(dir, 'plugin/.codex-plugin/plugin.json'))) return dir;
const parent = path.dirname(dir);
if (parent === dir) return null;
dir = parent;
}
} Try / catch
try {
installCodexPlugin();
} catch (err) {
if (err instanceof Error && err.message.includes('Could not locate a Codex marketplace root')) {
console.error('Run npx claude-mem@latest install from the repo root containing .agents/plugins/marketplace.json');
} else throw err;
} Prevention
- Execute installs from the directory containing .agents/plugins/marketplace.json.
- Do not gitignore .agents/ or plugin/.codex-plugin/ in repos used for installs.
- Pass an explicit marketplace root instead of relying on ancestor search in scripts/CI.
When it happens
Trigger: marketplaceRoot() -> resolvePluginMarketplaceRoot() is called (no preferredRoot, or the preferred root also failed) and every candidate, including all ancestors via findAncestorWithCodexMarketplace, is missing one or both required marker files.
Common situations: Running the CLI from an arbitrary directory (e.g. ~ or a script dir) far from any checkout; invoking from an npm global install where dot-directories were stripped; a fresh clone with .agents/ gitignored; a repo restructured so the marker files moved.
Related errors
- Codex marketplace root
- 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/0198768c4d783795.
Report an issue: GitHub.
Appendix: source
Thrown at src/services/integrations/CodexCliInstaller.ts:125
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);
if (resolved && missingMarketplaceFiles(resolved).length === 0) return resolved;
}
throw new Error('Could not locate a Codex marketplace root with .agents/plugins/marketplace.json and plugin/.codex-plugin/plugin.json. Run npx claude-mem@latest install from the package or repo root.');
}
function lookupCodexOnWindows(): string | null {
let stdout: string;
try {
stdout = execFileSync('where.exe', ['codex'], {
encoding: 'utf-8',
stdio: ['ignore', 'pipe', 'ignore'],
windowsHide: true,
});
} catch (error) {
const err = error instanceof Error ? error : new Error(String(error));
logger.warn('WORKER', 'Failed to locate codex via where; falling back to codex.cmd', { command: 'where codex' }, err);
return null;
}
const candidates = stdout
.split(/\r?\n/)View on GitHub (pinned to d8bc9755e7)