{"record":{"id":"dc7006eb01202194","repo":"Yeachan-Heo/oh-my-codex","slug":"native-hook-transaction-wrote-invalid-hooks-json","errorCode":null,"errorMessage":"Native hook transaction wrote invalid hooks.json: ${validation.error.message}","messagePattern":"Native hook transaction wrote invalid hooks\\.json: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/cli/setup.ts","lineNumber":1776,"sourceCode":"async function verifyNativeHookTransactionArtifact(\n\tapplied: AppliedNativeHookTransactionArtifact,\n): Promise<void> {\n\tconst { artifact } = applied;\n\tinjectNativeHookTransactionFailure(\"before_readback\", artifact);\n\tconst actual = await captureNativeHookTransactionArtifact(artifact.path, artifact.label);\n\tif (!nativeHookTransactionSnapshotsEqual(actual, applied.appliedSnapshot)) {\n\t\tthrow new Error(\n\t\t\t`Native hook transaction read-back changed for ${artifact.label}; refusing to overwrite concurrent content.`,\n\t\t);\n\t}\n\tif (artifact.after === null) return;\n\tconst content = decodeNativeHookTransactionUtf8(actual.bytes!, artifact.label);\n\tif (artifact.kind === \"hooks\") {\n\t\tconst validation = validateCodexHooksConfigStrict(content, {\n\t\t\tplatform: artifact.hookPlatform,\n\t\t});\n\t\tif (!validation.ok) {\n\t\t\tthrow new Error(\n\t\t\t\t`Native hook transaction wrote invalid hooks.json: ${validation.error.message}`,\n\t\t\t);\n\t\t}\n\t}\n\tif (artifact.kind === \"config\") TOML.parse(content);\n}\n\nasync function restoreNativeHookTransactionArtifact(\n\tapplied: AppliedNativeHookTransactionArtifact,\n\tancestorPrecondition: NativeHookTransactionAncestorPrecondition,\n\ttracker: RegularFileDurabilityTracker,\n\tassertRollbackState: () => Promise<void>,\n): Promise<void> {\n\tconst { artifact } = applied;\n\tconst current = await captureNativeHookTransactionArtifact(artifact.path, artifact.label);\n\tif (!nativeHookTransactionSnapshotsEqual(current, applied.appliedSnapshot)) {\n\t\tthrow new Error(\n\t\t\t`Native hook transaction rollback preserved ${artifact.path} for manual recovery because ${artifact.label} no longer matches the transaction-owned version.`,","sourceCodeStart":1758,"sourceCodeEnd":1794,"githubUrl":"https://github.com/Yeachan-Heo/oh-my-codex/blob/3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2/src/cli/setup.ts#L1758-L1794","documentation":"After a native hook transaction writes hooks.json to disk, setup re-reads the bytes and runs strict validation against the expected Codex hooks schema. If the written file does not conform, the transaction aborts with this error, indicating the write path produced content that would break Codex hook loading. It protects against corruption, partial writes, or bad hook generation.","triggerScenarios":"Calling the native hook transaction apply path with a hooks artifact whose serialized JSON fails validateCodexHooksConfigStrict for the configured hookPlatform; e.g. hook entries with wrong shape, invalid matcher syntax, or platform-specific fields missing.","commonSituations":"Custom hook templates with schema drift, a newer/older hooks schema version than the validator expects, encoding issues in decodeNativeHookTransactionUtf8, or test fault-injection that corrupts written bytes.","solutions":["Inspect validation.error.message to see which hook entry violates the Codex hooks schema","Validate your hook config with the same strict validator before starting the transaction","Ensure hook command/matcher fields match the platform (hooks.json vs platform-specific format) expected by your setup version","Check for non-UTF8 or truncated writes (disk issues, concurrent modifiers) by re-reading the file"],"exampleFix":"// before\nconst validation = validateCodexHooksConfigStrict(content, { platform: artifact.hookPlatform });\nif (!validation.ok) throw new Error(validation.error.message);\n// after\nconst validation = validateCodexHooksConfigStrict(content, { platform: artifact.hookPlatform });\nif (!validation.ok) {\n\tconsole.error(`hooks.json invalid: ${validation.error.message}`);\n\t// abort transaction, keep prior hooks.json\n\tthrow new Error(`Native hook transaction wrote invalid hooks.json: ${validation.error.message}`);\n}","handlingStrategy":"validation","validationCode":"import { validateCodexHooksConfigStrict } from \"./setup\";\nconst parsed = JSON.parse(hooksJson);\nconst check = validateCodexHooksConfigStrict(parsed, { platform: \"codex\" });\nif (!check.ok) {\n  console.error(\"hooks.json invalid:\", check.error.message);\n  process.exit(1);\n}","typeGuard":"const isPlainObject = (v: unknown): v is Record<string, unknown> =>\n  typeof v === \"object\" && v !== null && !Array.isArray(v);","tryCatchPattern":"try { await runSetup(); } catch (e) { if (e instanceof Error && e.message.startsWith(\"Native hook transaction wrote invalid hooks.json:\")) { /* keep prior hooks.json, log validation details, fix config */ } else throw e; }","preventionTips":["Pre-validate hook configs with the strict validator before starting setup","Pin setup/library versions so schema and validator stay in sync","Avoid concurrent tools editing hooks.json during setup"],"tags":["hooks","validation","transaction","codex","json-schema"],"backgroundTag":"config-validation-failed","analyzedSha":"3ad79a8a6fe6e95fdbb8c00e40716fffe4011ce2","analyzedAt":"2026-08-27T22:18:39.783Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}