kopia/kopia · error

not a local filesystem

Error message

not a local filesystem

What it means

createOSSnapshot on Windows (upload_os_snapshot_windows.go:26) requires the root fs.Directory to map to a real local path, needed for VSS shadow-copy detection. It calls root.LocalFilesystemPath(); when that returns "" the root is not backed by a local filesystem, so the error is thrown instead of attempting VSS.

Solutions

  1. Ensure the snapshot source root is a local directory (LocalFilesystemPath returns a non-empty path).
  2. Disable OS snapshots for non-local sources in the policy.
  3. If using a network share, snapshot the underlying local volume path instead.

Example fix

// before: root = s3-backed fs.Directory passed to createOSSnapshot
// after: only call createOSSnapshot when root.LocalFilesystemPath() != ""
Defensive patterns

Strategy: validation

Validate before calling

if root.LocalFilesystemPath() == "" {
    return errors.New("OS snapshot requires a local filesystem root")
}

Try / catch

newRoot, cleanup, err := createOSSnapshot(ctx, root, pol)
if err != nil && strings.Contains(err.Error(), "not a local filesystem") {
    log.Warnf("skipping OS snapshot for non-local source")
}

Prevention

When it happens

Trigger: Calling createOSSnapshot with a root directory that is a remote/webdav/s3-backed or in-memory fs.Directory whose LocalFilesystemPath() returns empty.

Common situations: Running an OS snapshot upload against a repository/source rooted on a network share or cloud provider rather than a local volume; tests using a memory filesystem.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of kopia/kopia@82495e54b5 (2026-09-07). Data as JSON: /api/errors/38d7130eab29b130. Report an issue: GitHub.

Appendix: source

Thrown at snapshot/upload/upload_os_snapshot_windows.go:26

	"github.com/mxk/go-vss"
	"github.com/pkg/errors"

	"github.com/kopia/kopia/fs"
	"github.com/kopia/kopia/fs/localfs"
	"github.com/kopia/kopia/internal/clock"
	"github.com/kopia/kopia/snapshot/policy"
)

func osSnapshotMode(p *policy.OSSnapshotPolicy) policy.OSSnapshotMode {
	return p.VolumeShadowCopy.Enable.OrDefault(policy.OSSnapshotNever)
}

//nolint:wrapcheck
func createOSSnapshot(ctx context.Context, root fs.Directory, _ *policy.OSSnapshotPolicy) (newRoot fs.Directory, cleanup func(), finalErr error) {
	local := root.LocalFilesystemPath()
	if local == "" {
		return nil, nil, errors.New("not a local filesystem")
	}

	ok, err := vss.IsShadowCopy(local)
	if err != nil {
		uploadLog(ctx).Warnf("failed to determine whether path is a volume shadow copy: %s (%v)", local, err)
	} else if ok {
		uploadLog(ctx).Warnf("path is already a volume shadow copy (skipping creation): %s", local)
		return root, func() {}, nil
	}

	vol, rel, err := vss.SplitVolume(local)
	if err != nil {
		return nil, nil, err
	}

	uploadLog(ctx).Infof("creating volume shadow copy of %v", vol)

	id, err := vss.Create(vol)

View on GitHub (pinned to 82495e54b5)