Skip to content

Fix fatal redeclare from leftover legacy include/ directory - #415

Merged
TheWitness merged 3 commits into
developfrom
fix/legacy-include-redeclare
Oct 6, 2026
Merged

TheWitness merged 3 commits into
developfrom
fix/legacy-include-redeclare

Conversation

@TheWitness

Copy link
Copy Markdown
Member

Problem

On installs upgraded from the old layout, the plugin fatals and Cacti auto-disables it:

ERROR PHP COMPILE_ERROR in Plugin 'intropage': Cannot redeclare intropage_get_allowed_devices()
(previously declared in .../plugins/intropage/include/functions.php:34)
in file: .../plugins/intropage/includes/functions.php on line: 47

The library directory moved from include/ to includes/. After an upgrade, the old include/ directory lingers on disk and stale plugin_hooks rows still point at include/<file>. When a stale hook (e.g. graph_buttons) fires, Cacti loads include/functions.php; the plugin's own code then loads includes/functions.php, redeclaring every shared function → fatal.

The existing repoint + prune logic lives inside intropage_upgrade_database(), which runs from display_information() / the config-check hook — too late: the stale hook fires earlier in the same request, and once Cacti disables the plugin the migration never runs again, so the install is permanently stuck.

Fix

Add intropage_cleanup_legacy_include() and call it at the top of intropage_config_arrays() — the earliest per-page hook, always registered from setup.php (a file that was never under include/, so its hook row is never stale). Before any stale graph_buttons/console_after hook can load the old library, it:

  1. Repoints any remaining plugin_hooks row from include/ to includes/ (fixes future requests), and
  2. Physically removes the leftover include/ directory (so a hook target cached for the current request can no longer load a second copy of the library).

It early-returns when include/ is absent, so it's a cheap is_dir() no-op on healthy installs. Reuses the existing plugin_intropage_rmtree() helper and logs a warning if removal is blocked by permissions.

Testing

  • php -l setup.php passes.

@TheWitness
TheWitness requested review from bmfmancini and xmacan and a balanced review from Copilot October 6, 2026 17:18

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Cleanup can miss stale hooks and follow a symlink outside the plugin directory, and the recovery behavior lacks tests.

Review effort: Balanced
Findings: 1 High severity

Open (1)
What changed in this PR

Adds early cleanup for legacy include/ installations to prevent fatal function redeclarations.

Changes:

  • Repoints stale plugin hook paths.
  • Removes the legacy directory before later hooks execute.
  • Documents the fix in the changelog.
File Description
setup.php Adds and invokes legacy-directory cleanup.
CHANGELOG.md Records the upgrade fix.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread setup.php Outdated
xmacan
xmacan previously approved these changes Oct 6, 2026
@TheWitness
TheWitness merged commit 817ca6d into develop Oct 6, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants