Nanoc

Troubleshooting

Error: “Found 3 content files for X; expected 0 or 1”

This error occurs for legacy identifiers when there are multiple files with the same base name, but different extensions. When using legacy identifiers, Nanoc requires each base name to be unique. For example, the following situation will give raise to this error:

content/assets/fonts/foo.eot
content/assets/fonts/foo.otf

Nanoc converts these filenames to identifiers which do not contain the file extension. In the example given above, both filenames correspond to the identifier /assets/fonts/foo/. Identifiers are required to be unique, and thus Nanoc raises an error.

New in Nanoc 4 are full identifiers, which contain the file extension. We recommend upgrading to Nanoc 4 and enabling full identifiers as well as glob patterns. For details, see the Nanoc 4 upgrade guide page and the Identifiers and patterns page.

Error: “can’t modify frozen…”

Once the compilation process has started, content, and attributes of layouts and items are frozen, which means they cannot be modified anymore. For example, the following rule is invalid and will cause a “can’t modify frozen Array” error:

compile '/articles/**/*'
  item[:tags] << 'article'
  filter :erb
  layout 'default'
end

What is possible, is modifying content and attributes in the preprocess phase. The preprocess phase is defined using the preprocess block in the Rules file (see the Rules page). For example:

preprocess do
  items.select { |i| i.identifier =~ '/articles/**/*' }.each do |i|
    i[:tags] << 'article'
  end
end

Error: “Textual filters cannot be used on binary items”

There are two item types in Nanoc: textual and binary. Most filters that come with Nanoc, such as :erb and :haml, are textual, meaning they take text as input and produce new text. It is also possible to define binary filters, such as an image thumbnail filter.

It is not possible to run a textual filter on binary items; for example, running :erb on an item with filename content/assets/images/puppy.jpg will cause the “Textual filters cannot be used on binary items” error.

When you are getting this error unexpectedly, double-check your Rules file and make sure that no binary item is filtered through a textual filter. Remember that Nanoc will use the first matching rule only!

Character encoding issues

Character encoding issues manifest themselves in two ways:

  • Some characters do not show up correctly in the output (e.g., ä shows up as ä).

  • Nanoc exits with an error such as RegexpError: invalid multibyte character.

In both cases, text in one character encoding is erroneously interpreted as a different character encoding. There are two possible causes for this.

Wrong output encoding tag

The text could be in the correct encoding, but Nanoc or the browser interpret it wrongly.

Nanoc’s output is always UTF-8, so the output files should not declare a different encoding. For example, having <meta charset="iso-8859-1"> at the top of files in output/ is wrong: it should be <meta charset="utf-8"> instead. You should also ensure that your web server sends the right Content-Type.

Wrong input encoding

The data sources could interpret the input data in the wrong encoding.

Nanoc defaults to the current environment encoding, which might not be what you expect. If the environment encoding does not match the actual file encoding, it can lead to errors in the output. There are three ways to solve this:

  • You can re-encode your site’s files. If your content files are not in UTF-8, this is probably a good start. Re-encoding into something else than UTF-8 is not recommended.

  • You can modify your environment encoding to match the file encoding. If you run into encoding issues with other sites or libraries, it isn’t a bad idea to set your environment up as UTF-8 and get it over with. You should not change your environment to a non-UTF-8 encoding, as UTF-8 is considered the standard character encoding.

  • You can set an explicit encoding in the Nanoc configuration file. This is the recommended approach, as it never hurts to be explicit.

To set the encoding explicitly in the site configuration, open nanoc.yaml (or config.yaml on older Nanoc sites) and navigate to the section where the data sources are defined. Unless you have modified this section, you will find a single entry for the filesystem data source there. In this section, add something similar to encoding: utf-8 (replacing utf-8 with whatever you really want). It could look like this:

data_sources:
  -
    type: filesystem
    encoding: utf-8

For bonus points, you can do all three. Setting up your content, environment, and configuration as UTF-8 is the best way to avoid encoding issues now and in the future.

Timestamps in YAML files parsed incorrectly

If you work with date/time attributes (such as created_at, published_at, and updated_at) and find that the time is one or more hours off, then this section applies to you.

If you use timestamps in the YAML file, be sure to include the timezone. If no timezone is specified, then UTC is assumed—not the local time zone! Quoting the YAML timestamp specification:

If the time zone is omitted, the timestamp is assumed to be specified in UTC. The time part may be omitted altogether, resulting in a date format. In such a case, the time part is assumed to be 00:00:00Z (start of day, UTC).

We recommend always specifying the time zone.

Hidden files are ignored

Nanoc by default intentionally ignores files and directories that have a name that starts with a period. Such files and directories are hidden on Unix-like systems, such as OS X and Linux. Nanoc does so because these hidden files and directories are often generated unintentionally; for instance, OS X will generate .DS_Store files, and vim generates backup files with a name like .about.md.un~.

The filesystem data source can be told to include specific files that would otherwise be ignored. To do so, specify in the data source’s extra_files attribute the patterns for the files that you would like to be included. For example, the following will include GitHub’s .nojekyll file and all files in the .well-known/ directory:

data_sources:
  -
    type: filesystem
    extra_files:
      - "/.well-known/**/*"
      - "/.nojekyll"

Alternatively, route a file whose name does not start with a slash to a path that starts with a slash. For example, the following will copy content/nojekyll to output/.nojekyll:

compile '/nojekyll' do
  write '/.nojekyll'
end

My helper methods cause a NoMethodError!

When calling a method in a helper results in a NoMethodError, you might not have activated the helper. To activate a helper, include it, like this (in a file in the lib/ directory, such as lib/helpers.rb):

include Nanoc::Helpers::Blogging

Make sure to double-check the spelling of the method that is being invoked.

Error: CannotDetermineFilter

This error occurs when the compilation rule for an item refers to a layout for which no rule exists. For example, a rules file that contains nothing but the following will raise this error:

compile '/index.html' do
  layout '/default.*'
  write '/index.html'
end

To fix this error, ensure that a rule exists for the layout. The example above can be fixed as follows (assuming that the default layout has the filename layouts/default.erb):

compile '/index.html' do
  layout '/default.*'
  write '/index.html'
end

layout '/*.erb', :erb

Error: InvalidEncoding

This error occurs when the file content cannot be interpreted in the encoding that Nanoc has inferred. For example, the following piece of code will generate a file that will cause an InvalidEncoding error if Nanoc assumes the file to be encoded as UTF-8:

File.write('content/broken.md', '¿', encoding: 'ISO-8859-1')

See the Character encoding issues section for details on how to fix this issue.

Error: InvalidFormat

This error occurs when Nanoc detects the presence of frontmatter, but the frontmatter isn’t terminated properly. For example, the following file will cause an InvalidFormat error, because the frontmatter is missing a final ---:

---
title: Home

Here is some content.

To fix this error, terminate the frontmatter properly. For example:

---
title: Home
---

Here is some content.

This error can also occur when the file is not supposed to have frontmatter, and the initial --- is meant to be part of the file content. For example, the following will also raise an InvalidFormat error:

---

This file starts with three dashes!

To tell Nanoc to treat these three dashes part of the content, rather than signaling the start of the frontmatter, add an artificial empty frontmatter:

---
---

---

This file starts with three dashes!

Error: InvalidMetadata

This error occurs when the frontmatter is not a collection of key-value pairs. For example, the following file will cause an UnparseableMetadata error:

---
My about page
---

Hello! This page has some details about myself.

To fix this error, ensure the YAML in the front matter is a collection of key-value pairs. For example:

---
title: My about page
---

Hello! This page has some details about myself.

This error can also occur when the file is not supposed to have frontmatter, and the initial --- is meant to be part of the file content. For example, the following will also raise an UnparseableMetadata error:

---

Once upon a time, …

---

Another section…

To tell Nanoc to treat these three dashes part of the content, rather than signaling the start of the frontmatter, add an artificial empty frontmatter:

---
---

---

Once upon a time, …

---

Another section…

Error: RecursiveCompilation

This error occurs when two or more items depend on each other’s compiled content. For example, imagine these two files:

<!-- content/foo.html -->
<%= @items['/bar.*'].compiled_content %>
<!-- content/bar.html -->
<%= @items['/foo.*'].compiled_content %>

The compiled content of the foo.html item depends on the compiled content of the bar.html item, and vice versa. Nanoc cannot resolve this, and throws a RecursiveCompilation error.

To fix this error, ensure that at least one of these items does not depend on the compiled content of the other.

This error also occurs when a single item depends on the later compiled content of itself. For example, an item with the following content will also cause a RecursiveCompilation error:

<%= @item.compiled_content %>

Error: UnknownDataSource

This error occurs when the nanoc.yaml configuration file lists a data source that is not known to Nanoc. For example, the following will cause an UnknownDataSource if the file_system data source is not defined:

data_sources:
  -
    type: file_system

To fix this error, verify that the data source name is spelled correctly. For example, the example above needs filesystem rather than file_system:

data_sources:
  -
    type: filesystem

This errors also occurs if the source files that define the data source have not yet been loaded. For example, if a (hypothetical) nanoc-aether gem defines a data source named aether, then that gem must be required before the data source can be used. In a file in the lib/ directory (e.g. lib/default.rb), add a require for the gem:

require 'nanoc-aether'

Error: UnknownFilter

This error occurs when a compilation rule calls a filter that Nanoc does not know about. For example, the following will cause an UnknownFilter error, assuming that there is no filter named :kram_down:

compile '/articles/*.md' do
  filter :kram_down
  layout '/article.*'
  write item.identifier.without_ext + '/index.html'
end

To fix this error, verify the spelling of the filter name in the rules file. The example above errors because the filter name is misspelled as kram_down; fixing the spelling to kramdown makes the error disappear:

compile '/articles/*.md' do
  filter :kramdown
  layout '/article.*'
  write item.identifier.without_ext + '/index.html'
end

This errors also occurs if the source files that define the filter have not yet been loaded. For example, if a (hypothetical) nanoc-transmogrify gem defines a filter named transmogrify, then that gem must be required before the filter can be used. In a file in the lib/ directory (e.g. lib/default.rb), add a require for the gem:

require 'nanoc-transmogrify'

Error: UnknownLayout

This error occurs when the compilation rule for an item specifies a layout that does not exist. For example, the rule below will cause an UnknownLayout error, assuming that there is no layout with an identifier matching the /atricle.* pattern:

compile '/articles/*.md' do
  filter :kramdown
  layout '/atricle.*'
  write item.identifier.without_ext + '/index.html'
end

To fix this error, verify that the layout exists and has the correct identifier, and verify that the correct identifier is used in the rules. In the example above, the identifier of the layout is misspelled as /atricle.*, and fixing the spelling by changing it to /article.* makes the error disappear:

compile '/articles/*.md' do
  filter :kramdown
  layout '/article.*'
  write item.identifier.without_ext + '/index.html'
end

Error: UnparseableMetadata

This error occurs when the frontmatter is not valid YAML. For example, the following file will cause an UnparseableMetadata error:

---
[Not valid YAML!
---

Here is some content.

To fix this error, ensure the YAML in the front matter is valid. For example:

---
title: Home
---

Here is some content.

For more information about YAML, see the YAML for Ruby guide, as well as the YAML specification.

This error can also occur when the file is not supposed to have frontmatter, and the initial --- is meant to be part of the file content. For example, the following will also raise an UnparseableMetadata error:

---

[0, 1[ is the interval that contains all real numbers between zero and one, including zero, but not including one.

---

Another section…

To tell Nanoc to treat these three dashes part of the content, rather than signaling the start of the frontmatter, add an artificial empty frontmatter:

---
---

---

[0, 1[ is the interval that contains all real numbers between zero and one, including zero, but not including one.

---

Another section…