thedotmack/claude-mem · critical · Error
Hand-edited Windows shell string detected in ${filePath} (${
Error message
Hand-edited Windows shell string detected in ${filePath} (${dottedPath}). It no longer matches src/build/hook-shell-template.ts. Regenerate via `node scripts/build-hooks.js --write-shell-templates` after an intentional generator change. What it means
The Windows-specific half of the Rule A guard from [3]. For manifest entries where expected is an object (not a bare string), the verifier also compares entry.commandWindows against expected.commandWindows. A mismatch on the Windows launcher string throws this. Triggered identically to [3] but only when the generator emits a distinct Windows command.
Source
Thrown at scripts/build-hooks.js:207
for (const [dottedPath, expected] of Object.entries(spec.commands)) {
const entry = hookEntryByPath(parsed, dottedPath);
const expectedCommand = typeof expected === 'string' ? expected : expected.command;
const actual = entry?.command ?? null;
if (actual !== expectedCommand) {
if (!writeMode || !entry) {
throw new Error(
`Hand-edited shell string detected in ${filePath} (${dottedPath}). It no longer matches src/build/hook-shell-template.ts. ` +
`Regenerate via \`node scripts/build-hooks.js --write-shell-templates\` after an intentional generator change.`
);
}
entry.command = expectedCommand;
dirty = true;
}
if (typeof expected !== 'string') {
const actualWindows = entry?.commandWindows ?? null;
if (actualWindows !== expected.commandWindows) {
if (!writeMode || !entry) {
throw new Error(
`Hand-edited Windows shell string detected in ${filePath} (${dottedPath}). It no longer matches src/build/hook-shell-template.ts. ` +
`Regenerate via \`node scripts/build-hooks.js --write-shell-templates\` after an intentional generator change.`
);
}
entry.commandWindows = expected.commandWindows;
dirty = true;
}
}
}
}
if (dirty) {
fs.writeFileSync(filePath, JSON.stringify(parsed, null, 2) + '\n');
console.log(` ✏️ Regenerated shell templates in ${filePath}`);
}
}
// Rule C safety net (bun-runner.js fixBrokenScriptPath) must stay documented.
const bunRunner = fs.readFileSync('plugin/scripts/bun-runner.js', 'utf-8');View on GitHub (pinned to d768ba3643)
Solutions
- Run node scripts/build-hooks.js --write-shell-templates to rewrite commandWindows from buildCodexWindowsCommand.
- If the entry is missing, restore the hook entry in the JSON first (the regenerator needs a target object), then re-run.
- Otherwise revert the hand edit: git checkout -- <filePath>.
- Confirm the verifier prints '✓ Rule A shell templates match the canonical generator'.
Example fix
# before: Windows launcher hand-edited "commandWindows": "powershell -File old.ps1" node scripts/build-hooks.js --write-shell-templates # after: commandWindows matches buildCodexWindowsCommand output
Defensive patterns
Strategy: validation
Validate before calling
// CI step: node scripts/build-hooks.js (verifier; non-zero exit on Windows-launcher drift) // Confirms every entry.commandWindows matches buildCodexWindowsCommand output.
Type guard
function hasWindowsCommand(entry): entry is { commandWindows: string } {
return entry != null && typeof entry.commandWindows === 'string';
} Try / catch
// Build-time only. Resolve by regenerating (--write-shell-templates) or reverting // the Windows launcher hand edit. Never catch/suppress.
Prevention
- Treat commandWindows as fully generator-owned; do not hand-edit even for Windows testing.
- Keep buildCodexWindowsCommand in the template as the single source of truth.
- Run the build on Windows CI too, so Windows-only drift is caught early.
When it happens
Trigger: A hooks JSON has entry.commandWindows that differs from buildCodexWindowsCommand output. Fires during node scripts/build-hooks.js verification when writeMode is off, or when on but the entry itself is absent so the regenerator cannot populate commandWindows.
Common situations: Editing the Windows branch of a hook by hand. Changing buildCodexWindowsCommand in src/build/hook-shell-template.ts without regenerating. Removing a hook entry while the manifest still expects a commandWindows field.
Related errors
- Hand-edited shell string detected in ${filePath} (mcp-search
- Hand-edited shell string detected in ${filePath} (${dottedPa
- plugin/scripts/bun-runner.js is missing fixBrokenScriptPath
- plugin/scripts/bun-runner.js uses optional chaining (?.) or
- mcp-server.cjs contains a Bun-only ${bunRequireMatch[0]} cal
AI-assisted analysis of thedotmack/claude-mem@d768ba3643 (2026-08-12).
Data as JSON: /api/errors/d316d288cffe3469.
Report an issue: GitHub.