affaan-m/ECC · error
does not line up with :\n
Error message
${METADATA_FILENAME} does not line up with ${hooksPath}:\n ${mismatches.join('\n ')} What it means
assertMetadataAligned() compares the hooks configuration against the metadata sidecar via findMetadataMismatches() and, if any mismatch is found, throws an error listing each mismatched location. It is the final gate in mergeHooksMetadata() ensuring the sidecar (METADATA_FILENAME) describes exactly the hooks present in hooksPath — same entries, same order/positions — before the merged result is accepted.
Solutions
- Read the mismatch list in the error message — each line names the event/index that disagrees — and fix those spots in whichever file is stale.
- Re-run the ECC merge/refresh tooling (which maintains the sidecar) instead of hand-editing hooks.json alone.
- If one file is authoritative, regenerate the other: refresh sidecar fingerprints from hooks.json, or restore hooks.json from the sidecar's recorded state.
- Ensure both files come from the same branch/commit (avoid mixed-checkout states).
Example fix
// before: hooks.json edited (new hook added) but .claude/hooks-metadata.json not updated assertMetadataAligned(cfg, metadata, hooksPath); // throws with mismatch list // after: update sidecar to include the new entry's fingerprint at matching position metadata.entries.Stop.splice(0, 0, fingerprintOf(newHook)); assertMetadataAligned(cfg, metadata, hooksPath); // passes
Defensive patterns
Strategy: try-catch
Validate before calling
const mismatches = findMetadataMismatches(hooksConfig, metadata);
if (mismatches.length > 0) {
console.error('Sidecar out of sync; run the ECC merge tooling or restore the matching sidecar before merging.');
process.exit(1);
}
mergeHooksMetadata(/* ... */); Type guard
function isMetadataInSync(hooksConfig, metadata) {
return findMetadataMismatches(hooksConfig, metadata).length === 0;
} Try / catch
try {
mergeHooksMetadata(/* ... */);
} catch (err) {
if (String(err.message).includes('does not line up with')) {
console.error(err.message); // prints the per-location mismatch list
console.error('Fix each listed location in the stale file, or restore both files from the same commit.');
} else throw err;
} Prevention
- Always edit hooks via mergeHooksMetadata/addJsonMergeOperation so the sidecar updates together.
- Commit hooks.json and its metadata sidecar in the same commit; never restore one without the other.
- After branch switches, verify both files come from the same tree before running hooks tooling.
- Read the mismatch list in the error — it pinpoints exactly which entries to fix.
When it happens
Trigger: Calling mergeHooksMetadata() (directly or through validateHooks flows) when hooks.json and the metadata sidecar disagree: entries added/removed in hooks.json only, fingerprints recomputed in one file but not the other, or a sidecar from a different project/branch copied over.
Common situations: Manually editing hooks.json without updating the sidecar; switching git branches where the two files diverged; restoring only one of the pair from backup; concurrent edits from two ECC sessions.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- Metadata reorder detected at
- artifact lacks genre binding
- audit health evidence does not match its evaluation
- Canonical session snapshot requires aggregates.workerCount…
- Claude settings contains multiple hooks for event
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/afe72c9f180cdf1d.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/hooks-config.js:270
for (const [event, eventMetadata] of Object.entries(entriesByEvent)) {
const entries = Array.isArray(events[event]) ? events[event] : [];
refreshed[event] = Array.isArray(eventMetadata)
? eventMetadata.map((entry, index) => (
entry && typeof entry === 'object' && index < entries.length
? { ...entry, fingerprint: fingerprintHookEntry(entries[index]) }
: entry
))
: eventMetadata;
}
return { ...metadata, entries: refreshed };
}
function assertMetadataAligned(hooksConfig, metadata, hooksPath) {
const mismatches = findMetadataMismatches(hooksConfig, metadata);
if (mismatches.length > 0) {
throw new Error(
`${METADATA_FILENAME} does not line up with ${hooksPath}:\n ${mismatches.join('\n ')}`
);
}
}
/**
* Merge a sidecar into a hooks config, rejecting a sidecar that does not line
* up. Shared by the readers below so a truncated or reordered sidecar fails
* loudly instead of producing entries with the wrong or missing ids.
*
* @param {object} hooksConfig - Parsed hooks.json.
* @param {object} metadata - Parsed hooks.metadata.json.
* @param {string} hooksPath - Used in the error message.
* @returns {object} a new merged hooks configuration
*/
function mergeHooksMetadata(hooksConfig, metadata, hooksPath = HOOKS_FILENAME) {
assertMetadataAligned(hooksConfig, metadata, hooksPath);
return applyHooksMetadata(hooksConfig, metadata);View on GitHub (pinned to 8321021c54)