Skip to content

Bug: Plugin path resolution uses marketplace.json file path instead of marketplace directory #11278

@maximelb

Description

@maximelb

Bug Report: Plugin Path Resolution Incorrectly Uses marketplace.json File Path Instead of Marketplace Directory

Environment

  • Claude Code Version: 2.0.36
  • OS: Linux 6.6.76
  • Platform: linux

Summary

When installing plugins from a local marketplace, Claude Code incorrectly constructs plugin installation paths by using the full marketplace.json file path (including the filename) as the base directory, instead of using the marketplace directory as the base. This causes all plugins to fail loading with "Plugin directory not found" errors.

Steps to Reproduce

  1. Create a local marketplace with the following structure:
marketplace/
├── .claude-plugin/
│   └── marketplace.json
└── plugins/
    ├── lc_query/
    │   └── .claude-plugin/
    │       └── plugin.json
    └── lc_external_datasources/
        └── .claude-plugin/
            └── plugin.json
  1. Configure marketplace.json with relative plugin paths:
{
  "name": "limacharlie-marketplace",
  "plugins": [
    {
      "name": "lc-query",
      "source": "./plugins/lc_query",
      "version": "1.0.0"
    },
    {
      "name": "lc-external-datasources",
      "source": "./plugins/lc_external_datasources",
      "version": "1.0.0"
    }
  ]
}
  1. Add the marketplace using /plugin command
  2. Install both plugins from the marketplace

Expected Behavior

Plugin paths should be resolved relative to the marketplace directory:

  • Base directory: /path/to/marketplace/
  • Relative source: ./plugins/lc_query
  • Expected result: /path/to/marketplace/plugins/lc_query

This is the standard behavior for resolving relative paths from configuration files - use the directory containing the config file, not the file itself.

Actual Behavior

Plugin paths are incorrectly resolved relative to the marketplace.json file path (including the filename):

  • Base (incorrect): /path/to/marketplace/.claude-plugin/marketplace.json
  • Relative source: ./plugins/lc_query
  • Actual result: /path/to/marketplace/.claude-plugin/marketplace.json/plugins/lc_query

This creates an invalid filesystem path (trying to use a file as a directory) that doesn't exist.

Error Messages

Plugin Loading Errors:

  ✘ lc-query@limacharlie-marketplace
     Plugin directory not found at path: /home/maxime/goProjects/github.com/refractionPOINT/documentation/marketplace/.claude-plugin/plugins/lc_query. Check that the marketplace entry has the correct path.
  ✘ lc-external-datasources@limacharlie-marketplace
     Plugin directory not found at path: /home/maxime/goProjects/github.com/refractionPOINT/documentation/marketplace/.claude-plugin/plugins/lc_external_datasources. Check that the marketplace entry has the correct path.

Note: The error shows Claude Code looking in marketplace/.claude-plugin/plugins/ rather than marketplace/plugins/, indicating the base path was resolved incorrectly during installation.

Evidence from Configuration Files

After installation, ~/.claude/plugins/installed_plugins.json contains:

{
  "version": 1,
  "plugins": {
    "lc-query@limacharlie-marketplace": {
      "installPath": "/home/maxime/goProjects/github.com/refractionPOINT/documentation/marketplace/.claude-plugin/marketplace.json/plugins/lc_query",
      "isLocal": true
    },
    "lc-external-datasources@limacharlie-marketplace": {
      "installPath": "/home/maxime/goProjects/github.com/refractionPOINT/documentation/marketplace/.claude-plugin/marketplace.json/plugins/lc_external_datasources",
      "isLocal": true
    }
  }
}

Notice the paths include marketplace.json/plugins/ which is invalid - marketplace.json is a file, not a directory.

Root Cause

The path resolution logic appears to be using the full marketplace.json file path as the base when resolving relative plugin source paths, instead of extracting the parent directory first.

Incorrect logic (current):

baseDir = marketplaceJsonPath  // e.g., "/path/to/.claude-plugin/marketplace.json"
pluginPath = resolve(baseDir, pluginSource)  // Results in invalid path

Correct logic (needed):

baseDir = dirname(dirname(marketplaceJsonPath))  // e.g., "/path/to/marketplace/"
pluginPath = resolve(baseDir, pluginSource)  // Results in valid path

Or more accurately, the base should be the marketplace root directory, which is the parent of .claude-plugin/.

Impact

  • Local marketplace plugins cannot be loaded
  • Plugins show as "installed" but are not accessible
  • Users see conflicting state (plugins listed as installed but with loading errors)
  • No workaround exists except restructuring the marketplace directory to match the incorrect path expectations

Suggested Fix

When resolving plugin source paths from marketplace.json:

  1. Take the marketplace.json file path
  2. Extract the parent directory (.claude-plugin/)
  3. Extract the parent of that (the marketplace root directory)
  4. Use the marketplace root directory as the base for resolving relative plugin paths

This ensures that "source": "./plugins/lc_query" correctly resolves relative to the marketplace root, not the config file.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workinghas reproHas detailed reproduction stepsplatform:linuxIssue specifically occurs on Linux

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions