Problem
openclaw plugins uninstall can report success while leaving invalid configuration behind. When plugins.load.paths contains a symlink to a copied managed plugin, uninstall deletes the target before its final config pass resolves the alias. The now-dangling alias is retained.
Reproduction
Using a freshly built and globally installed package from 9c0cf2b6a56f0da6c5c23928eb63f8223f980449 in isolated Linux state:
- Install a dependency-free local plugin through
openclaw plugins install so it is copied into the managed plugin directory.
- Create a symlink to that managed directory and add the alias to
plugins.load.paths, alongside an unrelated existing directory.
- Confirm fresh config validation succeeds, then run uninstall with
--dry-run.
- Run
openclaw plugins uninstall <id> --force, then validate config in a new process.
Observed: dry-run says the load path will be removed. Actual uninstall exits 0 and reports settings, install record, and directory removal, but omits the load path. The directory is gone, its alias remains in config, and fresh validation exits 1 with plugins.load.paths: plugin path not found. Original source files and the unrelated path survive.
Expected: remove the already-identified config reference while its filesystem identity is still available, retain safe retry state if file removal fails, and finish with valid config and accurate cleanup reporting.
Owner and scope
The CLI and managed-plugin lifecycles already plan cleanup before deletion, but their guarded disable write does not apply planned load-path removals. Recomputing identity after deleting files loses symlink information. The repair can reuse that existing guarded write and preserve the final config reread for concurrent edits, without broadening file ownership, adding a cache, or changing schemas/public configuration.
The before result comes from the real packaged CLI on Blacksmith Testbox 34028648873. The initial attempt stopped at npm-version preflight; a task-local npm 11.19 bootstrap allowed the unchanged scenario to run. This is an observed current-source bug; the introducing commit and first affected release are not established.
Problem
openclaw plugins uninstallcan report success while leaving invalid configuration behind. Whenplugins.load.pathscontains a symlink to a copied managed plugin, uninstall deletes the target before its final config pass resolves the alias. The now-dangling alias is retained.Reproduction
Using a freshly built and globally installed package from
9c0cf2b6a56f0da6c5c23928eb63f8223f980449in isolated Linux state:openclaw plugins installso it is copied into the managed plugin directory.plugins.load.paths, alongside an unrelated existing directory.--dry-run.openclaw plugins uninstall <id> --force, then validate config in a new process.Observed: dry-run says the load path will be removed. Actual uninstall exits 0 and reports settings, install record, and directory removal, but omits the load path. The directory is gone, its alias remains in config, and fresh validation exits 1 with
plugins.load.paths: plugin path not found. Original source files and the unrelated path survive.Expected: remove the already-identified config reference while its filesystem identity is still available, retain safe retry state if file removal fails, and finish with valid config and accurate cleanup reporting.
Owner and scope
The CLI and managed-plugin lifecycles already plan cleanup before deletion, but their guarded disable write does not apply planned load-path removals. Recomputing identity after deleting files loses symlink information. The repair can reuse that existing guarded write and preserve the final config reread for concurrent edits, without broadening file ownership, adding a cache, or changing schemas/public configuration.
The before result comes from the real packaged CLI on Blacksmith Testbox 34028648873. The initial attempt stopped at npm-version preflight; a task-local npm 11.19 bootstrap allowed the unchanged scenario to run. This is an observed current-source bug; the introducing commit and first affected release are not established.