Summary
Two error handling issues that can cause silent failures and inconsistent state.
Bug 1: add() saves mpm.json before metadata
Location: paper/.../PluginLifecycleServiceImpl.kt (lines 174-185)
The add() method writes mpm.json first (lines 174-180), then saves metadata (lines 183-185). If the metadata save fails, mpm.json already contains the plugin entry but no corresponding metadata file exists. This creates an inconsistent state that will cause issues when listing or managing the plugin later.
Fix: Either save in reverse order (metadata first, then mpm.json), implement rollback on failure, or use a two-phase staging approach.
Bug 2: checkAllOutdated() silently ignores per-plugin failures
Location: paper/.../PluginInfoServiceImpl.kt (lines 271-308)
checkOutdated(PluginName(pluginName)).onRight { outdatedInfo ->
if (outdatedInfo != null) {
outdatedInfoList.add(outdatedInfo)
}
}
Uses .onRight { } which discards Left results entirely. The method returns outdatedInfoList.right() regardless, so callers never know which plugins failed to check. An unreachable repository or broken metadata will be silently skipped.
Fix: Return a partial result type (e.g., Pair<List<OutdatedInfo>, List<PluginCheckError>>) or aggregate errors and report them to the user.
Impact
- Orphaned entries in mpm.json with no metadata
- Users may miss available updates without knowing checks are failing
Summary
Two error handling issues that can cause silent failures and inconsistent state.
Bug 1: add() saves mpm.json before metadata
Location:
paper/.../PluginLifecycleServiceImpl.kt(lines 174-185)The
add()method writes mpm.json first (lines 174-180), then saves metadata (lines 183-185). If the metadata save fails, mpm.json already contains the plugin entry but no corresponding metadata file exists. This creates an inconsistent state that will cause issues when listing or managing the plugin later.Fix: Either save in reverse order (metadata first, then mpm.json), implement rollback on failure, or use a two-phase staging approach.
Bug 2: checkAllOutdated() silently ignores per-plugin failures
Location:
paper/.../PluginInfoServiceImpl.kt(lines 271-308)Uses
.onRight { }which discardsLeftresults entirely. The method returnsoutdatedInfoList.right()regardless, so callers never know which plugins failed to check. An unreachable repository or broken metadata will be silently skipped.Fix: Return a partial result type (e.g.,
Pair<List<OutdatedInfo>, List<PluginCheckError>>) or aggregate errors and report them to the user.Impact