gohugoio/hugo · error
got unexpected EOF when executing
Error message
got unexpected EOF when executing %q. The user running hugo must have read and execute permissions on this program. With execute permissions only, this error is thrown.
What it means
Returned by the Dart Sass toCSS path when c.transpiler.Execute returns an error whose message is exactly 'unexpected EOF'. Hugo interprets this specific embedded-protocol error as a filesystem permission problem: the dart-sass-embedded binary was invoked but the Hugo process lacks read permission on it (execute-only). The message guides the user to fix permissions on the binary.
Solutions
- Grant read+execute on the Dart Sass binary to the Hugo user, e.g. `chmod 0755 $(which sass)` or `chmod o+rx /path/to/dart-sass-embedded`.
- Ensure the user running hugo also owns or is in the owning group of the binary and its parent directories.
- Reinstall Dart Sass via a method that sets standard 0755 permissions.
Example fix
// before $ ls -l $(which sass) -rwx--x--x ... sass // after $ sudo chmod 0755 $(which sass) $ ls -l $(which sass) -rwxr-xr-x ... sass
Defensive patterns
Strategy: validation
Validate before calling
// Verify read+execute permission on the Dart Sass binary for the Hugo user.
func binaryReadable(bin string) error {
fi, err := os.Stat(bin)
if err != nil { return err }
mode := fi.Mode().Perm()
if mode&0004 == 0 { // others-read
return fmt.Errorf("%s not world-readable (mode %o); chmod 0755", bin, mode)
}
return nil
} Prevention
- Install Dart Sass with standard 0755 permissions.
- In containers, run Hugo as a user with read+execute on the binary and its directories.
- Add a CI check that asserts the binary mode is 0755.
When it happens
Trigger: css.Sass/ToCSS with transpiler='dartsass' runs, the embedded binary starts, but reading its executable image (or a temp/protocol file) fails because the running user has execute but not read permission on hugo.DartSassBinaryName, producing 'unexpected EOF' from the transpiler.
Common situations: Binary installed with mode 0711 or 0111 (execute-only, no read), common in hardened/containerized environments or when an installer drops read bits; running Hugo as a different user than the binary owner without group read.
Related errors
- failed to copy config dir to vendor dir
- failed to copy module file to vendor
- failed to copy module to vendor dir
- failed to copy to
- failed to copy resources to vendor dir
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/724d2c54318b23df.
Report an issue: GitHub.
Appendix: source
Thrown at resources/resource_transformers/tocss/dartsass/client.go:124
}
func (c *Client) Close() error {
if c.transpiler == nil {
return nil
}
return c.transpiler.Close()
}
func (c *Client) toCSS(args godartsass.Args, src io.Reader) (godartsass.Result, error) {
in := helpers.ReaderToString(src)
args.Source = in
res, err := c.transpiler.Execute(args)
if err != nil {
if err.Error() == "unexpected EOF" {
//lint:ignore ST1005 end user message.
return res, fmt.Errorf("got unexpected EOF when executing %q. The user running hugo must have read and execute permissions on this program. With execute permissions only, this error is thrown.", hugo.DartSassBinaryName)
}
return res, herrors.NewFileErrorFromFileInErr(err, hugofs.Os, herrors.OffsetMatcher)
}
return res, err
}
type Options struct {
// Hugo, will by default, just replace the extension of the source
// to .css, e.g. "scss/main.scss" becomes "scss/main.css". You can
// control this by setting this, e.g. "styles/main.css" will create
// a Resource with that as a base for RelPermalink etc.
TargetPath string
// Hugo automatically adds the entry directories (where the main.scss lives)
// for project and themes to the list of include paths sent to LibSASS.
// Any paths set in this setting will be appended. Note that these will be
// treated as relative to the working dir, i.e. no include paths outside theView on GitHub (pinned to 52c9bd7908)