{"record":{"id":"38d7130eab29b130","repo":"kopia/kopia","slug":"not-a-local-filesystem","errorCode":null,"errorMessage":"not a local filesystem","messagePattern":"not a local filesystem","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"snapshot/upload/upload_os_snapshot_windows.go","lineNumber":26,"sourceCode":"\n\t\"github.com/mxk/go-vss\"\n\t\"github.com/pkg/errors\"\n\n\t\"github.com/kopia/kopia/fs\"\n\t\"github.com/kopia/kopia/fs/localfs\"\n\t\"github.com/kopia/kopia/internal/clock\"\n\t\"github.com/kopia/kopia/snapshot/policy\"\n)\n\nfunc osSnapshotMode(p *policy.OSSnapshotPolicy) policy.OSSnapshotMode {\n\treturn p.VolumeShadowCopy.Enable.OrDefault(policy.OSSnapshotNever)\n}\n\n//nolint:wrapcheck\nfunc createOSSnapshot(ctx context.Context, root fs.Directory, _ *policy.OSSnapshotPolicy) (newRoot fs.Directory, cleanup func(), finalErr error) {\n\tlocal := root.LocalFilesystemPath()\n\tif local == \"\" {\n\t\treturn nil, nil, errors.New(\"not a local filesystem\")\n\t}\n\n\tok, err := vss.IsShadowCopy(local)\n\tif err != nil {\n\t\tuploadLog(ctx).Warnf(\"failed to determine whether path is a volume shadow copy: %s (%v)\", local, err)\n\t} else if ok {\n\t\tuploadLog(ctx).Warnf(\"path is already a volume shadow copy (skipping creation): %s\", local)\n\t\treturn root, func() {}, nil\n\t}\n\n\tvol, rel, err := vss.SplitVolume(local)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\n\tuploadLog(ctx).Infof(\"creating volume shadow copy of %v\", vol)\n\n\tid, err := vss.Create(vol)","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/kopia/kopia/blob/82495e54b584c1ef6073c9e1be048f57f8aef078/snapshot/upload/upload_os_snapshot_windows.go#L8-L44","documentation":"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.","triggerScenarios":"Calling createOSSnapshot with a root directory that is a remote/webdav/s3-backed or in-memory fs.Directory whose LocalFilesystemPath() returns empty.","commonSituations":"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.","solutions":["Ensure the snapshot source root is a local directory (LocalFilesystemPath returns a non-empty path).","Disable OS snapshots for non-local sources in the policy.","If using a network share, snapshot the underlying local volume path instead."],"exampleFix":"// before: root = s3-backed fs.Directory passed to createOSSnapshot\n// after: only call createOSSnapshot when root.LocalFilesystemPath() != \"\"","handlingStrategy":"validation","validationCode":"if root.LocalFilesystemPath() == \"\" {\n    return errors.New(\"OS snapshot requires a local filesystem root\")\n}","typeGuard":null,"tryCatchPattern":"newRoot, cleanup, err := createOSSnapshot(ctx, root, pol)\nif err != nil && strings.Contains(err.Error(), \"not a local filesystem\") {\n    log.Warnf(\"skipping OS snapshot for non-local source\")\n}","preventionTips":["Only enable OS snapshots for sources on local volumes.","Check LocalFilesystemPath() before requesting VSS snapshots.","Treat network/cloud-backed roots as ineligible for OS snapshotting."],"tags":["windows","vss","filesystem"],"backgroundTag":"incompatible-source-type","analyzedSha":"82495e54b584c1ef6073c9e1be048f57f8aef078","analyzedAt":"2026-09-07T20:35:21.689Z","contentChangedAt":"2026-09-07T20:35:21.689Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}