kopia/kopia · error
unable to read symlink
Error message
unable to read symlink
What it means
Raised in uploadSymlinkInternal when fs.Symlink.Readlink fails while snapshotting a symlink: the OS returned an error reading the link target — commonly because the symlink is dangling in a way the filesystem reports (e.g. path-based walkers on Windows), the entry was deleted concurrently with the walk, or platform-specific readlink limitations. The relative path being uploaded identifies the faulting entry.
Solutions
- Check whether the symlink still exists on disk and re-run the snapshot if it was transiently removed
- On Windows, ensure Developer Mode is enabled or the process runs elevated so symlink information is accessible
- Ignore symlink read errors via the uploader's ignore-permissions/readlier options when symlink targets are not required
- Re-run with caching disabled if a stale directory cache points at since-deleted symlinks
Defensive patterns
Strategy: retry
When it happens
Trigger: Thrown at snapshot/upload/upload.go:312 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of kopia/kopia@82495e54b5 (2026-09-07).
Data as JSON: /api/errors/20c1080309b2021c.
Report an issue: GitHub.
Appendix: source
Thrown at snapshot/upload/upload.go:312
de.FileSize = written
atomic.AddInt32(&u.stats.TotalFileCount, 1)
atomic.AddInt64(&u.stats.TotalFileSize, de.FileSize)
return de, nil
}
func (u *Uploader) uploadSymlinkInternal(ctx context.Context, relativePath string, f fs.Symlink, metadataComp compression.Name) (dirEntry *snapshot.DirEntry, ret error) {
u.Progress.HashingFile(relativePath)
defer func() {
u.Progress.FinishedFile(relativePath, ret)
}()
defer u.Progress.FinishedHashingFile(relativePath, f.Size())
target, err := f.Readlink(ctx)
if err != nil {
return nil, errors.Wrap(err, "unable to read symlink")
}
writer := u.repo.NewObjectWriter(ctx, object.WriterOptions{
Description: "SYMLINK:" + f.Name(),
MetadataCompressor: metadataComp,
})
defer writer.Close() //nolint:errcheck
written, err := u.copyWithProgress(writer, bytes.NewBufferString(target))
if err != nil {
return nil, err
}
r, err := writer.Result()
if err != nil {
return nil, errors.Wrap(err, "unable to get result")
}
View on GitHub (pinned to 82495e54b5)