multica-ai/multica · error

inspect plugin directory: %w

Error message

inspect plugin directory: %w

What it means

Returned by `multica plugin init` when os.ReadDir on the target directory fails with an error other than NotExist (cmd_plugin.go:85). A missing directory is fine — init will create it — but any other stat/read failure (permission denied, path component is a file, I/O error) aborts scaffolding.

Source

Thrown at server/cmd/multica/cmd_plugin.go:85

	pluginValidateCmd.Flags().String("output", "json", "Output format: table or json")
	pluginPackCmd.Flags().String("output", "", "Output ZIP path (required)")
	pluginPackCmd.Flags().String("format", "table", "Result format: table or json")
	pluginInstallCmd.Flags().String("workspace", "", "Workspace ID, slug, or ID prefix")
	pluginInstallCmd.Flags().String("output", "json", "Output format: table or json")
	pluginListCmd.Flags().String("workspace", "", "Workspace ID, slug, or ID prefix")
	pluginListCmd.Flags().String("output", "table", "Output format: table or json")
	pluginStatusCmd.Flags().String("workspace", "", "Workspace ID, slug, or ID prefix")
	pluginStatusCmd.Flags().String("output", "json", "Output format: table or json")
}

func runPluginInit(cmd *cobra.Command, args []string) error {
	dir := filepath.Clean(args[0])
	entries, err := os.ReadDir(dir)
	if err == nil && len(entries) > 0 {
		return fmt.Errorf("plugin directory %q is not empty", dir)
	}
	if err != nil && !os.IsNotExist(err) {
		return fmt.Errorf("inspect plugin directory: %w", err)
	}
	key, _ := cmd.Flags().GetString("key")
	name, _ := cmd.Flags().GetString("name")
	publisher, _ := cmd.Flags().GetString("publisher")
	manifest := plugincontract.Manifest{
		APIVersion: plugincontract.APIVersionV1,
		Kind:       plugincontract.KindPlugin,
		Metadata: plugincontract.Metadata{
			Key: key, Name: name, Description: "A workspace-private declarative Skill Plugin.", Version: "0.1.0", Publisher: publisher,
		},
		Compatibility: plugincontract.Compatibility{
			HostAPI: ">=1.0.0 <2.0.0",
			RequiredDaemonFeatures: []string{
				plugincontract.DaemonFeatureExecutionManifestV1,
				plugincontract.DaemonFeatureAgentSkillV1,
			},
		},
		RequestedCapabilities: []string{plugincontract.CapabilityAgentSkillContribute},

View on GitHub (pinned to 2c0912b6ec)

Solutions

  1. Check the path: `ls -la <dir>` and verify each parent component is a directory you can read.
  2. Fix permissions: `chmod +rx <parent-dir>` or run with appropriate privileges.
  3. Remount or wait out the unavailable network filesystem, then retry init.

Example fix

// before
multica plugin init ./README.md/plugin   // parent is a file -> inspect plugin directory: not a directory

// after
mkdir -p ./plugins/my-plugin
multica plugin init ./plugins/my-plugin
Defensive patterns

Strategy: validation

Validate before calling

info, err := os.Stat(dir)
if err != nil && !os.IsNotExist(err) { return err }
if err == nil && !info.IsDir() { return fmt.Errorf("%s is a file, not a directory", dir) }

Prevention

When it happens

Trigger: Target path traverses a file (e.g. ./notes.txt/sub); directory lacks read/execute permission for the current user; NFS/FUSE mount hiccup; path too long (ENAMETOOLONG).

Common situations: Typo'd path whose parent is a regular file; restrictive directory permissions in shared/managed environments; scaffolding onto an unmounted network share.

Related errors


AI-assisted analysis of multica-ai/multica@2c0912b6ec (2026-08-15). Data as JSON: /api/errors/6dbe68b2e635bcaf. Report an issue: GitHub.