larksuite/cli · error

plugin %q %s filesystem: %w

Error message

plugin %q %s filesystem: %w

What it means

pathError builds the canonical error for every failure of the plugin skill filesystem: an fs.PathError whose Err wraps 'plugin "<owner>" <field> filesystem: <cause>'. It attributes the failure to the plugin (owner) and which overlay field (Base/Overlay) it came from, wrapping the underlying cause so errors.Is on fs.ErrNotExist and friends still works.

Source

Thrown at internal/skillpolicy/pluginfs.go:125

			name:   name,
			isDir:  entry.IsDir(),
			typ:    entry.Type(),
		}
	}
	return safe, nil
}

func (p *pluginFS) recoverPath(op, path string, err *error) {
	if value := recover(); value != nil {
		*err = p.pathError(op, path, fmt.Errorf("panic: %v", value))
	}
}

func (p *pluginFS) pathError(op, path string, cause error) error {
	return &fs.PathError{
		Op:   op,
		Path: path,
		Err:  fmt.Errorf("plugin %q %s filesystem: %w", p.owner, p.field, cause),
	}
}

var errorsNilResult = fmt.Errorf("returned nil without an error")

func joinPath(parent, child string) string {
	if parent == "." {
		return child
	}
	return parent + "/" + child
}

type pluginFile struct {
	fsys   *pluginFS
	path   string
	source fs.File
}

View on GitHub (pinned to 7fd6ef3c07)

Solutions

  1. Unwrap the fs.PathError.Err and inspect the innermost cause with errors.Is/errors.As (fs.ErrNotExist, fs.ErrPermission, etc.).
  2. Check the plugin named in the message and the Base/Overlay field to find which contributed filesystem is faulty.
  3. For ErrNotExist causes, verify the requested path exists in the plugin's Overlay with the exact name.
  4. For plugin authors: make the FS return valid errors and never (nil, nil).

Example fix

// handling the wrapped error as a caller
file, err := protected.Open("my-skill/SKILL.md")
if err != nil {
    var perr *fs.PathError
    if errors.As(err, &perr) && errors.Is(perr.Err, fs.ErrNotExist) {
        // skill missing from plugin overlay
    }
}
Defensive patterns

Strategy: type-guard

Type guard

func AsPluginPathError(err error) (*fs.PathError, bool) {
    var perr *fs.PathError
    if errors.As(err, &perr) && strings.Contains(perr.Err.Error(), "plugin ") {
        return perr, true
    }
    return nil, false
}

Try / catch

if err != nil {
    var perr *fs.PathError
    if errors.As(err, &perr) {
        // perr.Op, perr.Path attribute the failing operation
        // errors.Is(perr.Err, fs.ErrNotExist) still works through the wrap
    }
}

Prevention

When it happens

Trigger: Any Open/Stat/ReadFile/ReadDir/Read/Close on the protected plugin FS fails: the plugin returns an error, returns nil with nil error (errorsNilResult), or panics (converted by the recovery boundaries).

Common situations: A plugin Overlay lacks a requested SKILL.md path; a plugin FS returns fs.ErrPermission; a plugin's directory entries contain a nil DirEntry; a host-integrator's Base FS is misconfigured.

Related errors


AI-assisted analysis of larksuite/cli@7fd6ef3c07 (2026-09-04). Data as JSON: /api/errors/39aac5ba2eef3b65. Report an issue: GitHub.