[BUG]: Plugin Registering Twice #4064

Closed
opened 2026-02-16 17:42:29 -05:00 by yindo · 7 comments
Owner

Originally created by @EvanZhouDev on GitHub (Jan 1, 2026).

Originally assigned to: @rekram1-node on GitHub.

Description

If you make a new plugin that has a session.idle hook, the plugin appears to be registering twice, with the session.idle hook being called twice.

OpenCode version

1.0.223

Steps to reproduce

Make a plugin like this:

export const MyPlugin: Plugin = async (ctx: PluginInput) => {
        let times = 0;
        return {
		event: async ({ event }) => {
			if (event.type === "session.idle") {
				console.log("Hello" + times++);
			}
		},
	};
}

You will observe the logs happening twice:

Hello0
Hello0

However, now move the declaration of times outside the plugin:
let times = 0;

export const MyPlugin: Plugin = async (ctx: PluginInput) => {
        return {
		event: async ({ event }) => {
			if (event.type === "session.idle") {
				console.log("Hello" + times++);
			}
		},
	};
}

You will now observe logs as such:

Hello0
Hello1

For one, this is unexpected because the event listener seems to be triggering twice.
But based off these logs, it seems like the plugin itself is registering twice?

Originally created by @EvanZhouDev on GitHub (Jan 1, 2026). Originally assigned to: @rekram1-node on GitHub. ### Description If you make a new plugin that has a `session.idle` hook, the plugin appears to be registering twice, with the `session.idle` hook being called twice. ### OpenCode version 1.0.223 ### Steps to reproduce Make a plugin like this: ```ts export const MyPlugin: Plugin = async (ctx: PluginInput) => { let times = 0; return { event: async ({ event }) => { if (event.type === "session.idle") { console.log("Hello" + times++); } }, }; } ``` You will observe the logs happening twice: ``` Hello0 Hello0 ``` However, now move the declaration of times outside the plugin: let times = 0; ```ts export const MyPlugin: Plugin = async (ctx: PluginInput) => { return { event: async ({ event }) => { if (event.type === "session.idle") { console.log("Hello" + times++); } }, }; } ``` You will now observe logs as such: ``` Hello0 Hello1 ``` For one, this is unexpected because the event listener seems to be triggering twice. But based off these logs, it seems like the plugin itself is registering twice?
yindo added the bug label 2026-02-16 17:42:29 -05:00
yindo closed this issue 2026-02-16 17:42:29 -05:00
Author
Owner

@github-actions[bot] commented on GitHub (Jan 1, 2026):

This issue might be a duplicate of existing issues. Please check:

  • #3744: plugin events are fired multiple times

This appears to be related to a broader plugin event firing issue where events are being triggered multiple times instead of just once. Feel free to ignore if this is a different scenario.

@github-actions[bot] commented on GitHub (Jan 1, 2026): This issue might be a duplicate of existing issues. Please check: - #3744: plugin events are fired multiple times This appears to be related to a broader plugin event firing issue where events are being triggered multiple times instead of just once. Feel free to ignore if this is a different scenario.
Author
Owner

@arsham commented on GitHub (Jan 1, 2026):

Check this in two places:

  • In the configuration directory
  • Somewhere else

I had this before and it seems that in the configuration it loads them twice, once for it being global config and once for the project local. If that is the case, you can use this trick to avoid loading the plugin twice:

let IS_MYPLUGIN_REGISTERED = false;

export const Myplugin: Plugin = async ({ client, directory }) => {
  // Prevent double-registration when plugin loads from both global + local config
  if (IS_MYPLUGIN_REGISTERED) {
    return {};
  }
  IS_MYPLUGIN_REGISTERED = true;
}
@arsham commented on GitHub (Jan 1, 2026): Check this in two places: - In the configuration directory - Somewhere else I had this before and it seems that in the configuration it loads them twice, once for it being global config and once for the project local. If that is the case, you can use this trick to avoid loading the plugin twice: ```typescript let IS_MYPLUGIN_REGISTERED = false; export const Myplugin: Plugin = async ({ client, directory }) => { // Prevent double-registration when plugin loads from both global + local config if (IS_MYPLUGIN_REGISTERED) { return {}; } IS_MYPLUGIN_REGISTERED = true; } ```
Author
Owner

@EvanZhouDev commented on GitHub (Jan 1, 2026):

That's essentially what I ended up doing... but in my case I did check that my configuration only loads it once.

@EvanZhouDev commented on GitHub (Jan 1, 2026): That's essentially what I ended up doing... but in my case I did check that my configuration only loads it once.
Author
Owner

@rekram1-node commented on GitHub (Jan 1, 2026):

@EvanZhouDev could be happening if the session has a subagent? Subagent sessions also have idle events

@rekram1-node commented on GitHub (Jan 1, 2026): @EvanZhouDev could be happening if the session has a subagent? Subagent sessions also have idle events
Author
Owner

@EvanZhouDev commented on GitHub (Jan 1, 2026):

I think I'm doing this weird thing with Git worktrees for my OpenCode config which is perhaps causing this but I think I checked all viable configuration files and it is only loading it once... I don't have a subagent.

Edit: In addition, my plugin is only existent in my current worktree, so it shouldn't be registering twice because of that.

Would it make sense to make it by default only load a plugin once so that this doesn't happen? And then maybe add an explicit flag that allows loading multiple times?

@EvanZhouDev commented on GitHub (Jan 1, 2026): I think I'm doing this weird thing with Git worktrees for my OpenCode config which is perhaps causing this but I think I checked all viable configuration files and it is only loading it once... I don't have a subagent. Edit: In addition, my plugin is only existent in my current worktree, so it shouldn't be registering twice because of that. Would it make sense to make it by default only load a plugin once so that this doesn't happen? And then maybe add an explicit flag that allows loading multiple times?
Author
Owner

@ShpetimA commented on GitHub (Jan 3, 2026):

@EvanZhouDev @rekram1-node I ran into the same issue while developing a plugin found the bug created pr feel free to check it out

@ShpetimA commented on GitHub (Jan 3, 2026): @EvanZhouDev @rekram1-node I ran into the same issue while developing a plugin found the bug created pr feel free to check it out
Author
Owner

@ShpetimA commented on GitHub (Jan 3, 2026):

Btw @arsham and @EvanZhouDev you can also fix it without updating opencode by just having one export for your plugin
export const YourPlugin
either
export default YourPlugin

if you have both this issue happens

@ShpetimA commented on GitHub (Jan 3, 2026): Btw @arsham and @EvanZhouDev you can also fix it without updating opencode by just having one export for your plugin _export const YourPlugin_ either _export default YourPlugin_ if you have both this issue happens
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#4064