9 Errors
dxtr edited this page 2026-10-18 16:23:02 +02:00

Errors

freetype-error

Every failure in cl-ft2 is signalled as one flat condition class, freetype-error, a subclass of error. It covers three cases:

  1. A FreeType function returned a non-zero FT_Error.
  2. cl-ft2 saw that a call could not succeed and stopped it before it reached FreeType: a destroyed object, a glyph index out of range, a strike or instance that does not exist, an outline asked of a bitmap, or a variation on a font without axes.
  3. No FreeType could be loaded when cl-ft2 was. The error is named :cannot-open-resource; its message lists each file tried and why it failed, and its hint says how to get FreeType:
cl-ft2 could not load FreeType: Could not load the foreign library LIBFREETYPE.
  libfreetype.so.6: Error opening shared object "libfreetype.so.6": …
  libfreetype.so: Error opening shared object "libfreetype.so": …
Install FreeType 2.13.1 or newer: on Debian or Ubuntu, libfreetype6.

On Windows the hint asks to restore native\windows-x64\freetype.dll from the repository.

Reader Value
freetype-error-message what went wrong, in terms of the cl-ft2 call (a string)
freetype-error-hint what to do about it (a string), or nil
freetype-error-name a keyword that classifies the error, such as :cannot-open-resource, or :unknown
freetype-error-code the integer FT_Error code. For errors cl-ft2 caught itself, the code FreeType uses for that kind of problem
freetype-error-function the FreeType function that failed, such as "FT_New_Face", or nil when cl-ft2 caught the problem itself

The report prints the message, then the hint, then the FreeType function and error name when there is one:

(handler-case (ft2:open-face lib "/no/such/font.ttf")
  (ft2:freetype-error (e)
    (values (ft2:freetype-error-name e)
            (ft2:freetype-error-code e)
            (princ-to-string e))))
;; => :CANNOT-OPEN-RESOURCE
;;    1
;;    "Could not open the font /no/such/font.ttf: the file does not exist or cannot be read.
;;     Check the path and the file's permissions.
;;     (FreeType: FT_New_Face returned cannot-open-resource)"

Dispatch on freetype-error-name, not on the message text:

(defun try-open (lib path)
  (handler-case (ft2:open-face lib path)
    (ft2:freetype-error (e)
      (case (ft2:freetype-error-name e)
        ((:cannot-open-resource) nil)                 ; missing: skip it
        ((:unknown-file-format :invalid-file-format)  ; not a usable font
         (warn "~A is not a usable font" path) nil)
        (t (error e))))))

Errors you are likely to meet

Name Typical cause Hint given
:cannot-open-resource file missing or unreadable; when loading cl-ft2, no FreeType found check the path and permissions; install FreeType
:unknown-file-format not a font, or a format FreeType does not know pass a font file FreeType supports
:invalid-file-format, :invalid-table, :invalid-offset damaged font use another copy
:invalid-stream-operation octet vector too short or truncated —
:invalid-argument bad face index, strike that does not exist, instance index out of range, too many coordinates, unknown axis tag, variation call on a static font specific to the call
:invalid-glyph-index index ≥ face-num-glyphs use char-index
:invalid-character-code code not valid in the current charmap pass a character or select a charmap
:invalid-charmap-handle setting face-charmap to a charmap from another face pass one of this face's charmaps
:invalid-glyph-format glyph-bitmap on an unrendered glyph, glyph-outline / transform-glyph / stroke-glyph on a bitmap render first, or load without :render
:cannot-render-glyph no renderer for the glyph's format —
:invalid-pixel-size, :invalid-ppem size not available in a bitmap-only face set face-strike to one of face-strikes
:missing-bitmap strike has no image for this glyph —
:invalid-library-handle library destroyed make a new library and keep it until you are done
:invalid-face-handle face destroyed (directly or by destroy-library) reopen with open-face
:invalid-handle glyph or stroker destroyed make a new one
:invalid-outline make-outline given arrays FreeType cannot use; the message says what is wrong give two coordinates and a tag for each point, and each contour's last point
:array-too-large a stroke with more points than an outline holds stroke fewer or simpler contours at a time
:out-of-memory FreeType could not allocate memory —
:unimplemented-feature FreeType does not support this for this font —

Errors caught by cl-ft2 itself read like this:

Glyph index 999999 is out of range: DejaVu Sans has 6253 glyphs.
Glyph indexes run from 0 below FACE-NUM-GLYPHS; CHAR-INDEX gives the
glyph for a character.
The face has no bitmap strikes, so strike 0 does not exist.
Set the size of a scalable face with FACE-SIZE.

freetype-error-name knows FreeType's whole public error table (fterrdef.h), about 100 codes covering TrueType bytecode, BDF/PCF and stream errors, whether or not your FreeType was built with error strings. Module-specific codes are classified by their low byte, which is FreeType's base error.

Bad arguments: type-error

Arguments of the wrong type or kind are rejected with a standard type-error before anything reaches FreeType or cl-ffi:

  • an unknown keyword for a load flag, hinting target, render mode, encoding, kerning mode, line cap, line join, stroke border or fill rule
  • an open for stroke-outline that is neither a boolean nor a sequence of one for each contour
  • a negative or non-integer size, index or radius
  • a variation axis tag that is not four characters, or a box for render-outline beyond 2^23 pixels
  • an object of the wrong kind, such as a glyph where a face belongs, or a keyword where a library belongs
(ft2:load-glyph face 1 :flags '(:bogus))
;; type-error: The value :BOGUS is not of type
;;   (MEMBER :NO-SVG :BITMAP-METRICS-ONLY … :NO-HINTING :NO-SCALE)

Every exported function declares these types, so SBCL checks them on entry and warns at compile time about a constant that does not fit. The report is SBCL's:

(ft2:render-outline lib outline 4 4 :x 1e9)
;; type-error: The value 1.0e9 is not of type (REAL -8388608 8388608) when binding :X

So a freetype-error always means the arguments were well-formed: the font, the state of the object, or FreeType itself refused the call.