agalwood/Motrix · critical · AggregateError
plugin locale prepare-commit and rollback both failed
Error message
plugin locale prepare-commit and rollback both failed
What it means
Thrown by PluginRegistry.setHostLanguageTransaction: the prepare phase completed, options.beforeCommit() threw, then options.rollbackHostLocale(previousLanguage) also threw. Unlike error 205, the registry's own in-memory state had not yet been committed — only the caller's prepare hook and its rollback hook both failed, so the two errors are wrapped in an AggregateError.
Source
Thrown at src/core/plugin/plugin-registry.ts:412
options: HostLanguageTransactionOptions
): Promise<boolean> {
const shouldCommit = options.shouldCommit ?? (() => true)
for (;;) {
if (!shouldCommit()) return false
const prepared = await this.prepareHostLanguage(language)
if (!this.canCommitHostLanguage(prepared, shouldCommit)) {
if (!shouldCommit()) return false
continue
}
const previousLanguage = this.currentLang
try {
await options.beforeCommit?.()
} catch (error) {
try {
await options.rollbackHostLocale(previousLanguage)
} catch (rollbackError) {
throw new AggregateError(
[error, rollbackError],
'plugin locale prepare-commit and rollback both failed'
)
}
throw error
}
if (!this.canCommitHostLanguage(prepared, shouldCommit)) {
await options.rollbackHostLocale(previousLanguage)
if (!shouldCommit()) return false
continue
}
const committed = await this.commitHostLanguage(
prepared,
options.commitHostLocale,
options.rollbackHostLocale,
shouldCommit
)View on GitHub (pinned to 1a708ee577)
Solutions
- Read AggregateError.errors[0] (beforeCommit) and AggregateError.errors[1] (rollbackHostLocale) to find the shared failing dependency.
- Repair the shared resource both callbacks rely on (release the file lock, restore IPC, fix permissions).
- Make rollbackHostLocale resilient — never re-throw the same class of failure; log and continue so the original error surfaces cleanly.
- Retry setHostLanguageTransaction once the dependency is healthy.
Example fix
// before — rollback re-throws on the same IPC failure
beforeCommit: () => hostIpc.persistLocale(lang),
rollbackHostLocale: () => hostIpc.persistLocale(prev)
// after — rollback degrades gracefully
rollbackHostLocale: (prev) => hostIpc.persistLocale(prev).catch(e => log.error('rollback failed', e)) Defensive patterns
Strategy: try-catch
Type guard
function isAggregateError(e: unknown): e is AggregateError {
return e instanceof Error && Array.isArray((e as AggregateError).errors)
} Try / catch
try {
await registry.setHostLanguageTransaction(language, {
beforeCommit: persistToHost,
rollbackHostLocale: rollbackOnHost,
commitHostLocale: commitOnHost,
shouldCommit: () => true,
})
} catch (e) {
if (e instanceof AggregateError) {
const [prepareErr, rollbackErr] = e.errors
log.error('locale prepare-commit AND rollback failed', { prepareErr, rollbackErr })
// registry in-memory state was not committed; safe to retry once the shared dependency recovers
} else throw e
} Prevention
- Ensure rollbackHostLocale cannot throw for the same reason beforeCommit does (different resource or try/catch inside).
- Test the transaction with a beforeCommit that deliberately fails and assert rollback succeeds.
- Keep the host-side locale IPC channel healthy so both phases can rely on it.
- Log inside rollback so its failures are diagnosable without re-throwing.
When it happens
Trigger: setHostLanguageTransaction() runs; options.beforeCommit rejects; the caller-supplied options.rollbackHostLocale also rejects. Common when beforeCommit and rollbackHostLocale both touch the same failing subsystem (host UI, IPC, disk).
Common situations: beforeCommit persists locale to a config file and rollbackHostLocale restores it, but the config file is locked/read-only. Host IPC is down so both the prepare-commit IPC and rollback IPC reject. A custom HostLanguageTransactionOptions implementation with a rollback that re-throws.
Related errors
- plugin locale commit and rollback both failed
- PLUGIN_MANIFEST_INVALID
- registry responded ${res.status}
- PLUGIN_MANIFEST_INVALID
- PLUGIN_MANIFEST_INVALID
AI-assisted analysis of agalwood/Motrix@1a708ee577 (2026-08-12).
Data as JSON: /api/errors/6e5108b574f85d05.
Report an issue: GitHub.