gohugoio/hugo · error
failed to parse file %q: %s
Error message
failed to parse file %q: %s
What it means
Returned by `hugo import jekyll` while converting an individual Jekyll post when `pageparser.ParseFrontMatterAndContent` cannot parse the post's front matter and body (commands/import.go:321-324). The file was read successfully and its `YYYY-MM-DD-title` filename parsed; the failure is in the content itself — Hugo's page parser can't split or decode the front matter block, which aborts the whole import (unlike a bad filename, which is merely skipped).
Source
Thrown at commands/import.go:323
if err != nil {
c.r.Printf("Failed to parse filename '%s': %s. Skipping.", filename, err)
return nil
}
log.Println(filename, postDate, postName)
targetFile := filepath.Join(targetDir, relPath)
targetParentDir := filepath.Dir(targetFile)
os.MkdirAll(targetParentDir, 0o777)
contentBytes, err := os.ReadFile(path)
if err != nil {
c.r.logger.Errorln("Read file error:", path)
return err
}
pf, err := pageparser.ParseFrontMatterAndContent(bytes.NewReader(contentBytes))
if err != nil {
return fmt.Errorf("failed to parse file %q: %s", filename, err)
}
newmetadata, err := c.convertJekyllMetaData(pf.FrontMatter, postName, postDate, draft)
if err != nil {
return fmt.Errorf("failed to convert metadata for file %q: %s", filename, err)
}
content, err := c.convertJekyllContent(newmetadata, string(pf.Content))
if err != nil {
return fmt.Errorf("failed to convert content for file %q: %s", filename, err)
}
fs := hugofs.Os
if err := helpers.WriteToDisk(targetFile, strings.NewReader(content), fs); err != nil {
return fmt.Errorf("failed to save file %q: %s", filename, err)
}
return nil
}
View on GitHub ↗ (pinned to 8a468df065)
Solutions
- The error names the file — open that _posts file and check the front matter block: matching `---` delimiters and valid YAML between them.
- Quote scalar values containing colons or special characters (title: "Foo: Bar") and replace tabs with spaces.
- Validate the front matter with yamllint or a YAML playground to find the exact syntax error.
- Fix and re-run the import (with --force if the target is now non-empty).
Example fix
# before (_posts/2015-03-01-hello.md) --- title: Hello: World --- # after --- title: "Hello: World" ---
Defensive patterns
Strategy: try-catch
Validate before calling
// Pre-lint source files for parseable front matter before importing
data, err := os.ReadFile(path)
if err != nil {
return err
}
if !bytes.HasPrefix(data, []byte("---")) && !bytes.HasPrefix(data, []byte("+++")) {
// flag file: missing/odd front matter delimiter likely to fail parsing
} Try / catch
if err := importFile(path); err != nil {
failures = append(failures, fmt.Sprintf("%s: %v", path, err))
continue // keep importing the rest, report failures at the end
} Prevention
- Validate front matter (YAML/TOML delimiters, encoding) in the source site before importing
- Fix or exclude known-malformed files rather than letting one abort the batch
- Run the import on a copy of the source so you can iterate on problem files safely
When it happens
Trigger: Importing a Jekyll site containing a `_posts` file with malformed front matter: unclosed `---` delimiters, invalid YAML inside the block (tabs for indentation, unquoted `:` in titles, duplicate keys), Liquid tags inside front matter values, or non-UTF-8 encoding that corrupts the delimiters.
Common situations: Old Jekyll posts with sloppy YAML that Jekyll's permissive parser tolerated but Hugo's stricter one rejects; posts with titles containing unescaped colons; merge-conflict markers left in front matter; CRLF/BOM issues from Windows-authored posts.
Related errors
- error processing file %q
- target path "%s" exists but is not a directory
- target path "%s" exists and is not empty
- failed to unmarshal config for path %q: %w
- failed to load config: %w
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/3928391510685779.json.
Report an issue: GitHub ↗.