nektos/act · error

compile %q: %w

Error message

compile %q: %w

What it means

In watch mode (act --watch), watchAndRun compiles the repository's .gitignore (if present) with gitignore.CompileIgnoreFile to filter which file changes trigger re-runs. If that file exists but cannot be compiled as a gitignore pattern set — unreadable bytes, invalid patterns the library rejects — the wrapped error 'compile <path>: %w' is returned and watch mode exits before starting the folder watcher.

Source

Thrown at cmd/root.go:770

	if err != nil {
		return err
	}

	return nil
}

func watchAndRun(ctx context.Context, fn common.Executor) error {
	dir, err := os.Getwd()
	if err != nil {
		return err
	}

	ignoreFile := filepath.Join(dir, ".gitignore")
	ignore := &gitignore.GitIgnore{}
	if info, err := os.Stat(ignoreFile); err == nil && !info.IsDir() {
		ignore, err = gitignore.CompileIgnoreFile(ignoreFile)
		if err != nil {
			return fmt.Errorf("compile %q: %w", ignoreFile, err)
		}
	}

	folderWatcher := fswatch.NewFolderWatcher(
		dir,
		true,
		ignore.MatchesPath,
		2, // 2 seconds
	)

	folderWatcher.Start()
	defer folderWatcher.Stop()

	// run once before watching
	if err := fn(ctx); err != nil {
		return err
	}

View on GitHub (pinned to 4f41128141)

Solutions

  1. Inspect and fix the .gitignore: remove or correct the offending pattern lines (look around the point the underlying error text mentions).
  2. Sanitize encoding: ensure the file is valid UTF-8 text (e.g. 'file .gitignore', re-save as UTF-8).
  3. Temporarily rename .gitignore away to confirm it is the culprit, then restore it cleaned.
  4. If the file is not needed, delete it — watch mode only compiles it when present.

Example fix

# before
# .gitignore contains a bad line like:
**/[]invalid[
act --watch   # compile "/repo/.gitignore": ...

# after
# fix or remove the invalid pattern, then:
act --watch
Defensive patterns

Strategy: try-catch

Validate before calling

package main

import (
	"fmt"
	"os"
	"unicode/utf8"
)

func checkGitignoreReadable(path string) error {
	info, err := os.Stat(path)
	if err != nil || info.IsDir() {
		return nil // absent is fine; watch mode skips it
	}
	data, err := os.ReadFile(path)
	if err != nil {
		return fmt.Errorf(".gitignore unreadable: %w", err)
	}
	if !utf8.Valid(data) {
		return fmt.Errorf(".gitignore is not valid UTF-8")
	}
	return nil
}

Try / catch

if err := watchAndRun(ctx, executor); err != nil {
    var compileErr *fmt.wrapError
    if errors.As(err, &compileErr) || strings.Contains(err.Error(), "compile \"") {
        return fmt.Errorf("fix or remove the malformed .gitignore, then rerun act --watch: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Running 'act --watch' in a repo whose .gitignore contains lines the gitignore compiler cannot parse, or that has permission/encoding problems (non-UTF-8 bytes, a directory in place of the file is excluded by the IsDir check, but unreadable perms are not).

Common situations: Corrupted or oddly-encoded .gitignore (CRLF/BOM usually fine, but binary junk breaks it); tools that rewrite .gitignore badly; restrictive file permissions after a repo copy; pathologically long or malformed glob lines.

Related errors


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