nektos/act · error
unable to readlink '%s': %w
Error message
unable to readlink '%s': %w
What it means
Returned when the billy filesystem's Readlink call fails while FileCollector processes a symlink encountered during the workspace walk. The error wraps the underlying OS/filesystem error and names the offending path, so the root cause (permission, dangling symlink, unsupported FS) is visible in %w.
Source
Thrown at pkg/filecollector/file_collector.go:181
}
} else {
return nil
}
}
if err == nil && entry.Mode == filemode.Submodule {
err = fc.Fs.Walk(file, fc.CollectFiles(ctx, split))
if err != nil {
return err
}
return filepath.SkipDir
}
path := filepath.ToSlash(sansPrefix)
// return on non-regular files (thanks to [kumo](https://medium.com/@komuw/just-like-you-did-fbdd7df829d3) for this suggested update)
if fi.Mode()&os.ModeSymlink == os.ModeSymlink {
linkName, err := fc.Fs.Readlink(file)
if err != nil {
return fmt.Errorf("unable to readlink '%s': %w", file, err)
}
return fc.Handler.WriteFile(path, fi, linkName, nil)
} else if !fi.Mode().IsRegular() {
return nil
}
// open file
f, err := fc.Fs.Open(file)
if err != nil {
return err
}
defer f.Close()
if ctx != nil {
// make io.Copy cancellable by closing the file
cpctx, cpfinish := context.WithCancel(ctx)
defer cpfinish()
go func() {View on GitHub (pinned to 4f41128141)
Solutions
- Run `find . -xtype l` in the workspace to locate dangling symlinks and fix or delete them.
- Check permissions on the symlink and its parent directory if running under a restricted user/container.
- Exclude the offending directory from collection (move it out of SrcPath or add ignore rules) if it is not needed inside the container.
Example fix
# locate broken symlinks before running act find . -xtype l -print delete_or_fix_each_of_them
Defensive patterns
Strategy: validation
Validate before calling
// before running act, verify no dangling symlinks exist in the workspace
err := filepath.Walk(src, func(p string, fi os.FileInfo, err error) error {
if err == nil && fi.Mode()&os.ModeSymlink != 0 {
if _, e := os.Readlink(p); e != nil { return fmt.Errorf("bad link %s: %w", p, e) }
}
return nil
}) Try / catch
if err != nil && strings.Contains(err.Error(), "unable to readlink") {
// report the named path, fix or remove the symlink, then retry the run
} Prevention
- Run `find . -xtype l` as a pre-flight check in CI before invoking act.
- Avoid committing broken node_modules/.bin-style links; regenerate them instead.
- Keep the workspace on a native filesystem, not a restrictive FUSE mount, when collecting files.
When it happens
Trigger: The walked tree contains a symlink that the filesystem implementation cannot read: a dangling symlink on a filesystem that disallows it, permission-restricted symlink targets, or a chroot/billy test FS whose Readlink is unimplemented for that path.
Common situations: Workspaces with broken symlinks (node_modules/.bin entries pointing at missing binaries), bind-mounted volumes with weird link semantics, or unit tests using in-memory filesystems that return errors from Readlink.
Related errors
- max depth %d of symlinks exceeded while reading %s
- --health-start-interval cannot be negative
- conflicting options: cannot attach both user-defined and non
- conflicting options: cannot specify both --network-alias and
- opening seccomp profile (%s) failed: %w
AI-assisted analysis of nektos/act@4f41128141 (2026-08-15).
Data as JSON: /api/errors/92113efb2c9b989e.
Report an issue: GitHub.