thedotmack/claude-mem · critical · Error
plugin/hooks/codex-hooks.json contains unknown Codex hook ev
Error message
plugin/hooks/codex-hooks.json contains unknown Codex hook event: ${eventName} What it means
Iterates Object.keys(codexHooks.hooks) and asserts each event name is in validCodexHookEvents (SessionStart, UserPromptSubmit, PreToolUse, PermissionRequest, PostToolUse, etc., defined at scripts/build-hooks.js ~680). A typo'd or unsupported event would be silently ignored by Codex, so the build fails fast and names the bad event.
Source
Thrown at scripts/build-hooks.js:735
'plugin/.mcp.json',
'.codex-plugin/plugin.json',
'.agents/plugins/marketplace.json',
];
for (const filePath of requiredDistributionFiles) {
if (!fs.existsSync(filePath)) {
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();View on GitHub (pinned to d768ba3643)
Solutions
- Open plugin/hooks/codex-hooks.json and rename the offending key to one of the supported events (see validCodexHookEvents in scripts/build-hooks.js).
- If you intended a Claude-only behaviour, move that hook into the Claude settings file, not codex-hooks.json.
- Re-run the build; the event-name check precedes the marketplace/MCP checks.
Example fix
// before
"hooks": { "PostTooluser": [ ... ] } // typo
// after
"hooks": { "PostToolUse": [ ... ] } Defensive patterns
Strategy: validation
Validate before calling
const VALID = new Set(['SessionStart','UserPromptSubmit','PreToolUse','PermissionRequest','PostToolUse','Stop','Notification','SubagentStop']); // mirror the build's validCodexHookEvents
const hooks = JSON.parse(fs.readFileSync('plugin/hooks/codex-hooks.json','utf8')).hooks ?? {};
const bad = Object.keys(hooks).filter(k => !VALID.has(k));
if (bad.length) throw new Error('Unknown codex hook events: ' + bad.join(',')); Type guard
function isKnownCodexEvent(name: string, valid: Set<string>): name is (typeof valid)[number] & string {
return valid.has(name);
} Try / catch
// Build-time only. Rename the event to one Codex emits, or move the hook into the // Claude settings file. Do not suppress.
Prevention
- Keep the Codex hook event list in sync with Codex's emitted events; update validCodexHookEvents when Codex adds events.
- Lint the codex-hooks.json keys against the allowed set in CI.
- Don't assume Claude and Codex share the same event names.
When it happens
Trigger: Adding a hook under an event name Codex doesn't emit (e.g. 'ToolCall', 'OnIdle', or a misspelling like 'PostTooluser'). Copying a Claude-only event into the Codex hooks file.
Common situations: Typo in an event name. Assuming event parity between Claude and Codex hooks when they differ. Renaming an event upstream without updating this file.
Related errors
- plugin/hooks/codex-hooks.json contains unsupported Codex roo
- Hand-edited shell string detected in ${filePath} (${dottedPa
- .agents/plugins/marketplace.json must point claude-mem sourc
- plugin/.mcp.json mcp-search launcher must include Codex cach
- 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/49f15d0605156dd2.
Report an issue: GitHub.