flipped-aurora/gin-vue-admin · error

plugin archive contains multiple web plugins

Error message

plugin archive contains multiple web plugins

What it means

Symmetric to the server-side check: the installer allows at most one web plugin part per archive. If it encounters a second distinct web plugin root (different name or path under the web side), it rejects the archive with this error.

Source

Thrown at server/service/system/auto_code_plugin.go:298

			if parts[index+1] != "plugin" || (parts[index] != "server" && parts[index] != "web") {
				continue
			}
			name := parts[index+2]
			if err := utils.ValidatePluginName(name); err != nil {
				return pluginArchive{}, err
			}
			part := &pluginArchivePart{
				root: filepath.Join(tempDir, filepath.FromSlash(strings.Join(parts[:index+2], "/"))),
				name: name,
			}
			if parts[index] == "server" {
				if archive.server != nil && (archive.server.name != part.name || archive.server.root != part.root) {
					return pluginArchive{}, errors.New("plugin archive contains multiple server plugins")
				}
				archive.server = part
			} else {
				if archive.web != nil && (archive.web.name != part.name || archive.web.root != part.root) {
					return pluginArchive{}, errors.New("plugin archive contains multiple web plugins")
				}
				archive.web = part
			}
			break
		}
	}
	if archive.server == nil && archive.web == nil {
		return pluginArchive{}, errors.New("invalid plugin archive")
	}
	return archive, nil
}

func pluginInstallRoot(component, parentPlugin string) (string, error) {
	root, err := utils.JoinWithinRoot(global.GVA_CONFIG.AutoCode.Root, component, "plugin")
	if err != nil || parentPlugin == "" {
		return root, err
	}
	parentPath, err := utils.JoinWithinRoot(root, parentPlugin)

View on GitHub (pinned to 3136500ef3)

Solutions

  1. Rebuild the archive with exactly one web plugin directory.
  2. Delete unrelated or stale web plugin directories from the zip.
  3. Install each web plugin using its own separate archive.

Example fix

// before (archive layout)
web/src/plugin/foo/
web/src/plugin/bar/
// after
web/src/plugin/foo/  // single web plugin per archive
Defensive patterns

Strategy: validation

Validate before calling

const webDirs = new Set(entries.filter(e => /(^|\/)web\/src\/plugin\/[^/]+\//.test(e)).map(e => e.split('/')[3]))
if (webDirs.size > 1) throw new Error(`archive has ${webDirs.size} web plugins: ${[...webDirs]}`)

Try / catch

try {
  await installPlugin(archive)
} catch (e) {
  if (e.message.includes('multiple web plugins')) {
    showHint('Split the archive: one web plugin per zip.')
  } else { throw e }
}

Prevention

When it happens

Trigger: Installing an archive containing multiple unique directories under the web root, e.g. `web/src/plugin/foo` and `web/src/plugin/bar`. findPluginArchive throws on the second distinct web part.

Common situations: Zipping the whole `web/src/plugin` directory; stale files from a previously extracted plugin left in the staging folder; packaging tools that bundle multiple frontend plugins.

Related errors


AI-assisted analysis of flipped-aurora/gin-vue-admin@3136500ef3 (2026-08-31). Data as JSON: /api/errors/912d8338476edf26. Report an issue: GitHub.