gohugoio/hugo · error
failed to save file %q:: %w
Error message
failed to save file %q:: %w
What it means
Returned by `hugo convert` when the converted page cannot be written back to disk via `helpers.WriteToDisk` (commands/convert.go:198-199). Parsing and re-encoding succeeded; the failure is purely at the filesystem write step for the computed target filename (in place, or under --output). The doubled colon is a formatting quirk in the source.
Source
Thrown at commands/convert.go:199
if err != nil {
site.Log.Errorln(errMsg)
return err
}
newContent.Write(pf.Content)
newFilename := p.File().Filename()
if c.outputDir != "" {
contentDir := strings.TrimSuffix(newFilename, p.File().Path())
contentDir = filepath.Base(contentDir)
newFilename = filepath.Join(c.outputDir, contentDir, p.File().Path())
}
fs := hugofs.Os
if err := helpers.WriteToDisk(newFilename, &newContent, fs); err != nil {
return fmt.Errorf("failed to save file %q:: %w", newFilename, err)
}
return nil
}
func (c *convertCommand) copyContentDirsForOutput(pagesBackedByFile page.Pages) error {
contentDirs := make(map[string]bool)
for _, p := range pagesBackedByFile {
filename := p.File().Filename()
contentDir := strings.TrimSuffix(filename, p.File().Path())
if contentDir == filename {
continue
}
contentDirs[filepath.Clean(contentDir)] = true
}
var contentDirList []string
for contentDir := range contentDirs {View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Check permissions on the reported path and its parent directory; ensure the user running hugo can write there (`ls -l`, chown/chmod as needed).
- If using --unsafe in-place conversion on a read-only mount, switch to `-o/--output <writable-dir>` instead.
- Verify free disk space and that no path component of the target is an existing regular file.
- On Windows, close editors/sync clients holding the file and re-run.
Example fix
# before hugo convert toYAML --unsafe # content/ is a read-only mount # after hugo convert toYAML -o /tmp/converted
Defensive patterns
Strategy: try-catch
Validate before calling
// Verify the output directory is writable before converting
f, err := os.CreateTemp(outputDir, ".writecheck*")
if err != nil {
return fmt.Errorf("output dir not writable: %w", err)
}
f.Close()
os.Remove(f.Name()) Try / catch
if err != nil {
var pathErr *fs.PathError
if errors.As(err, &pathErr) {
// permission/disk issue: report path and underlying errno, abort before more writes
}
} Prevention
- Check disk space and directory permissions before bulk save operations
- Use --output to write converted files to a fresh directory instead of overwriting sources
- Unwrap with errors.As to *fs.PathError to distinguish permission vs. disk-full causes
When it happens
Trigger: Running `hugo convert to*` where the target file or its parent directory is not writable: read-only content files or mounts, insufficient permissions on the --output directory, a full disk, a path component that exists as a file, or on Windows a file locked by another process (editor/sync client).
Common situations: Converting inside a Docker container with a read-only bind mount; content files checked out read-only; --output pointing at a protected system path; OneDrive/Dropbox locking files during write; disk-full CI runners.
Related errors
- failed to resolve output path %q: %w
- failed to copy %q to %q: %w
- failed to save file %q: %s
- failed to create workingDir: %w
- failed to open non-content file: %w
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/257165c3e35f7a53.json.
Report an issue: GitHub ↗.