affaan-m/ECC · error
FINAL_VERIFICATION_FAILED
FINAL_VERIFICATION_FAILED
Error message
Could not verify destination-only ${CURRENT_PLUGIN_ID} state after source cleanup. What it means
After a plugin scope migration removes the plugin from the source scope, verifyFinalState re-reads the plugin inventory and asserts the plugin now exists in the destination scope ONLY. If the final inventory does not match that expectation, it throws FINAL_VERIFICATION_FAILED with a message stating the destination-only state could not be verified, plus recovery commands. This prevents declaring success on a migration that left the system inconsistent.
Solutions
- Run the recoveryCommands included in the error to re-register the plugin in the destination scope
- Re-run migrateClaudePluginScope after closing other Claude Code sessions that may hold plugin state
- Manually inspect the destination scope's plugin config and the source scope's remnants, then remove duplicates
- Retry after any file-sync/lock settles, then confirm only the destination scope lists the plugin
Example fix
// before: destination config missing the plugin
{ "plugins": [] }
// after (or run the suggested recovery command)
{ "plugins": [{ "id": "everything-claude-code", "scope": "user" }] } Defensive patterns
Strategy: retry
Validate before calling
// before migrating, confirm no other session holds plugin state: // lsof <projectRoot>/.claude/plugins* and ensure destination config lists no conflicting entries
Try / catch
try { await migrateClaudePluginScope(); } catch (e) { if (e.code === 'FINAL_VERIFICATION_FAILED') { /* run e.recovery commands, then re-run migration */ } else throw e; } Prevention
- Close other Claude Code sessions during scope migration to avoid concurrent state writes
- Run migrations on a quiescent filesystem (no active sync tools on the project root)
- Re-run migration rather than manually editing plugin state when verification fails
When it happens
Trigger: migrateClaudePluginScope completes source cleanup but the final plugin inventory read shows the plugin missing from the destination scope, still present in the source scope, or the inventory file is unreadable/stale at the final-verification phase.
Common situations: Another process (Claude Code itself) rewrote plugin state between cleanup and verification; file locks or sync delays making the freshly written destination config not yet visible to the inventory reader; concurrent migrations racing on the same project root; a partially failed cleanup step earlier in the migration.
Related errors
- ! : invalid meta.json, continuing with defaults ( )
- DESTINATION_VERIFICATION_FAILED
- legacy scheduler jobs file must be a JSON object or array
- Legacy workspace not found
- Legacy workspace source must be a directory
AI-assisted analysis of affaan-m/ECC@8321021c54 (2026-09-16).
Data as JSON: /api/errors/e61fdd500af71c85.
Report an issue: GitHub.
Appendix: source
Thrown at scripts/lib/claude-scope-migration.js:238
} catch {
// Preserve the safest known two-scope state in the structured recovery.
}
throw migrationError(
'SOURCE_UNINSTALL_FAILED',
`The destination is installed, but Claude could not remove the ${migration.sourceScope} source scope.`,
{
phase: 'source-uninstall',
observedScopes,
recovery: recoveryCommands(migration.sourceScope, destinationScope),
}
);
}
}
function verifyFinalState(run, paths, destinationScope) {
const plugins = readPluginInventory(run, paths.projectRoot, 'final-verification');
return validateExpectedScopes(plugins, [destinationScope], {
code: 'FINAL_VERIFICATION_FAILED',
destinationScope,
message: `Could not verify destination-only ${CURRENT_PLUGIN_ID} state after source cleanup.`,
phase: 'final-verification',
recovery: recoveryCommands(null, destinationScope),
});
}
function migrateClaudePluginScope(options = {}, dependencies = {}) {
if (!VALID_SCOPES.has(options.scope)) {
throw migrationError(
'INVALID_SCOPE',
'Scope migration requires --scope user, project, or local.'
);
}
if (options.hooks !== undefined && !VALID_HOOK_MODES.has(options.hooks)) {
throw migrationError('INVALID_HOOK_MODE', `Invalid hook mode: ${options.hooks}`);
}
View on GitHub (pinned to 8321021c54)