Skip to content

Missing font license

A font you registered is not stating the terms it travels under: the declaration is missing, misshapen, or names a file Keystone cannot use. The build finishes, and a book that ships the font may ship it without the notice its license asks for.

What it looks like

An entry naming a face and nothing else:

my-serif:
  main:
    file: MySerif-Regular.otf
  css: '"My Serif", "Georgia", serif'
WARN: font 'my-serif' declares no license
  A font usually comes with a license file that has to be included wherever the
  font is. Keystone cannot tell which file that is until the entry names it.
  Books that embed this font will not include its license.
  Name the license file in the entry's main.license. Write an empty list where
  the font is yours and there is nothing to pass on.
  See https://keystone.knight-owl.dev/errors/missing-font-license/#a-font-that-declares-no-license

Or a declaration that is not a list of filenames — here the bare spelling YAML reads as a single string:

my-serif:
  main:
    file: MySerif-Regular.otf
    license: OFL.txt
  css: '"My Serif", "Georgia", serif'
WARN: font 'my-serif' license is a string, not a list
  A font can come with more than one license file, so main.license is always a
  list. Each entry is a filename in your fonts directory, not a path.
  The font ships without its license.
  Write main.license as a list, one filename per entry.
  See https://keystone.knight-owl.dev/errors/missing-font-license/#a-declaration-that-is-not-a-list-of-filenames

Or two texts that end up under one name:

my-serif:
  main:
    file: MySerif-Regular.otf
    license:
      - LICENSE
      - LICENSE.txt
  css: '"My Serif", "Georgia", serif'
WARN: font 'my-serif' names two licenses that cannot be told apart
  LICENSE
  LICENSE.txt
  Keystone adds .txt to a license name that does not have it, so two names
  differing only by that extension end up the same. Case is ignored too, because
  not every filesystem keeps it.
  One of the two files ships and the other does not.
  Rename one of the files, and the entry that names it, so the two differ by
  more than an extension or by case.
  See https://keystone.knight-owl.dev/errors/missing-font-license/#two-licenses-that-take-one-name

Or one naming terms that are not in fonts/:

my-serif:
  main:
    file: MySerif-Regular.otf
    license:
      - OFL.txt
  css: '"My Serif", "Georgia", serif'
WARN: font 'my-serif' has no license file named OFL.txt
  The font ships without its license.
  Check the name against the file in your fonts directory, or drop it from
  main.license.
  See https://keystone.knight-owl.dev/errors/missing-font-license/#a-license-that-cannot-be-read

What it means

A font you did not write comes with terms, and a book that carries the font file whole is passing the font on — so the terms go with it. Keystone can only make that happen if the entry names the file that states them.

So the entry is judged on its own, not against what you are building. It is either complete or it is not, and building a PDF today does not make an incomplete one right. The text lands in an EPUB, which carries whole font files; a PDF embeds a cut-down subset, which licenses generally exempt, and DOCX and ODT embed no font at all.

Every built-in family ships its license text beside its files, and each one the book embeds takes a copy into the archive. Your own fonts are the part Keystone cannot read: what their terms permit is yours to check.

None of these messages stops the build. Under strict mode every one of them does, which is where a book you are about to publish should meet them.

A font that declares no license

An entry with no main.license. Nothing has been said about the font's terms, which is not the same as saying it has none — and only you know which. That is why this warns rather than stopping: Keystone cannot tell an oversight from a font you drew yourself.

Name the license file, or say there is nothing to name

Drop the license text into fonts/ beside the font and name it in main.license. Fonts are usually distributed with one — OFL.txt, LICENSE, COPYING — and a family whose terms span two files takes both. If the font is yours and there is nothing to pass on, write an empty list: license: [] is an answer, and it silences this.

A declaration that is not a list of filenames

main.license is a list, even where it names one file, and each entry is the name of a file sitting in fonts/ beside the font. A bare license: OFL.txt is a string where a list belongs, and license: licenses/OFL.txt is a path where a name belongs.

Write it as a list of plain filenames

One name per entry, each a file in the same directory as the font — no folders, no paths. The shape is in Custom fonts.

Two licenses that take one name

LICENSE and LICENSE.txt end up as one name: a license name that does not end in .txt gains it, so only one of the two ships. Two names differing only in case end the same way, because not every filesystem a reader unpacks onto keeps the difference.

Rename one so the two differ by more than an extension

Give one of the files a name that stands apart with case ignored and with .txt discounted — OFL.txt and GPL.txt rather than LICENSE and LICENSE.txt — and update the entry that names it.

A license that cannot be read

main.license names a file Keystone could not open in your fonts directory. The font still works; its terms do not travel with it.

Match the name to the file, or drop it

Check the spelling against what sits in fonts/, case included — the same name that has to be there for main.file. If the file is gone and no terms apply, remove it from main.license rather than leaving the entry pointing at nothing.

  • Custom fonts — registering your own typeface, and what else Keystone checks about an entry.
  • Duplicate font file — two entries competing for one name in the same flat folder, which stops the build instead.