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

  1. Run `find . -xtype l` in the workspace to locate dangling symlinks and fix or delete them.
  2. Check permissions on the symlink and its parent directory if running under a restricted user/container.
  3. 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

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


AI-assisted analysis of nektos/act@4f41128141 (2026-08-15). Data as JSON: /api/errors/92113efb2c9b989e. Report an issue: GitHub.