thedotmack/claude-mem · critical · Error
.agents/plugins/marketplace.json must point claude-mem sourc
Error message
.agents/plugins/marketplace.json must point claude-mem source.path at ./plugin so Codex loads the bundled plugin root
What it means
Loads .agents/plugins/marketplace.json, finds the plugin whose name is 'claude-mem', and asserts its source.path equals './plugin'. Codex loads the bundled plugin root, so any other path (absolute, '../plugin', a cache path) would make Codex miss the bundled hooks/MCP server. The error explains the requirement.
Source
Thrown at scripts/build-hooks.js:741
throw new Error(`Missing required distribution file: ${filePath}`);
}
}
const codexHooks = JSON.parse(fs.readFileSync('plugin/hooks/codex-hooks.json', 'utf-8'));
const validCodexHookRootKeys = new Set(['hooks']);
for (const rootKey of Object.keys(codexHooks)) {
if (!validCodexHookRootKeys.has(rootKey)) {
throw new Error(`plugin/hooks/codex-hooks.json contains unsupported Codex root key: ${rootKey}`);
}
}
for (const eventName of Object.keys(codexHooks.hooks ?? {})) {
if (!validCodexHookEvents.has(eventName)) {
throw new Error(`plugin/hooks/codex-hooks.json contains unknown Codex hook event: ${eventName}`);
}
}
const codexMarketplace = JSON.parse(fs.readFileSync('.agents/plugins/marketplace.json', 'utf-8'));
const claudeMemMarketplaceEntry = (codexMarketplace.plugins ?? []).find((plugin) => plugin.name === 'claude-mem');
if (claudeMemMarketplaceEntry?.source?.path !== './plugin') {
throw new Error('.agents/plugins/marketplace.json must point claude-mem source.path at ./plugin so Codex loads the bundled plugin root');
}
const bundledMcp = JSON.parse(fs.readFileSync('plugin/.mcp.json', 'utf-8'));
const mcpSearchCommand = bundledMcp.mcpServers?.['mcp-search']?.args?.join(' ') ?? '';
if (!mcpSearchCommand.includes('.codex/plugins/cache/claude-mem-local/claude-mem')) {
throw new Error('plugin/.mcp.json mcp-search launcher must include Codex cache fallback for hosts that do not inject PLUGIN_ROOT');
}
if (!mcpSearchCommand.includes('plugins/cache/thedotmack/claude-mem')) {
throw new Error('plugin/.mcp.json mcp-search launcher must include Claude cache fallback for hosts that do not inject PLUGIN_ROOT');
}
console.log('✓ All required distribution files present');
await verifyShellTemplateCanonical();
console.log('\n✅ All build targets compiled successfully!');
console.log(` Output: ${hooksDir}/`);
console.log(` - Worker: worker-service.cjs`);
console.log(` - Server: server-service.cjs`);
console.log(` - MCP Server: mcp-server.cjs`);View on GitHub (pinned to d768ba3643)
Solutions
- Open .agents/plugins/marketplace.json and set the claude-mem entry's source.path back to './plugin'.
- If you genuinely need a different path for local testing, do it in a copy of the file outside the repo or via an env override — the committed file must read './plugin'.
- Re-run the build; the assertion at scripts/build-hooks.js:738-742 must pass.
Example fix
// before: .agents/plugins/marketplace.json
{ "plugins": [{ "name":"claude-mem", "source": { "path": "/home/me/claude-mem/plugin" } }] }
// after
{ "plugins": [{ "name":"claude-mem", "source": { "path": "./plugin" } }] } Defensive patterns
Strategy: validation
Validate before calling
const mp = JSON.parse(fs.readFileSync('.agents/plugins/marketplace.json','utf8'));
const entry = (mp.plugins ?? []).find(p => p.name === 'claude-mem');
if (!entry || entry.source?.path !== './plugin') {
throw new Error('marketplace claude-mem source.path must be ./plugin');
} Type guard
function pointsAtBundledPlugin(entry): boolean {
return entry?.source?.path === './plugin';
} Try / catch
// Build-time only. Set source.path back to './plugin'. For local testing, use a // separate (non-committed) marketplace file. Do not suppress.
Prevention
- Keep .agents/plugins/marketplace.json committed with source.path === './plugin'.
- Do local testing via a copy or an env-driven override, not by editing the committed file.
- CI should run the build so any drift fails the pipeline.
When it happens
Trigger: Editing .agents/plugins/marketplace.json and changing the claude-mem entry's source.path to a different value (absolute path, a cache dir, or a monorepo-relative path).
Common situations: Pointing source.path at a local dev checkout for testing and forgetting to revert. Automation that rewrites marketplace paths. A merge that brings in a different marketplace convention.
Related errors
- plugin/.mcp.json mcp-search launcher must include Codex cach
- plugin/hooks/codex-hooks.json contains unsupported Codex roo
- plugin/hooks/codex-hooks.json contains unknown Codex hook ev
- plugin/.mcp.json mcp-search launcher must include Claude cac
- Hand-edited shell string detected in ${filePath} (mcp-search
AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12).
Data as JSON: /api/errors/deb8244ba8c7c9d9.
Report an issue: GitHub.