Typst 编译报错怎么看:常见错误与解决办法
逐条解读 Typst 0.15.1 最常见的编译报错和警告:unknown variable(包括粘贴 LaTeX 公式时的 rac)、unclosed delimiter、expected expression、中文标点写进代码、类型错误、漏写 #、unknown font family、文件找不到与路径越出项目、标签和文献键不存在、宏包找不到或版本不对,每条都给出报错原文、原因和改法,以及 JointTex 里怎么看这些报错。
最后核对:2026-10-24Typst 的报错比 LaTeX 的好读得多:每条报错都指明文件、行号,并在源码下面用 ^ 标出出错的那一段,很多报错还附带改法提示。本文先说明怎么读一条 Typst 报错,再逐条列出最常见的报错,每条给出 Typst 0.15.1 的原文、原因和改法。错误写法只作为代码展示,可以直接打开的示例都是改好的版本。LaTeX 的报错见 LaTeX 编译报错。
先学会读报错
以公式里连写两个字母为例,Typst 的报错是这样的:
error: unknown variable: ab
┌─ main.typ:1:1
│
1 │ $ab + c$
│ ^^
│
= hint: if you meant to display multiple letters as is, try adding spaces between each letter: `a b`
= hint: or if you meant to display this as text, try placing it in quotes: `"ab"`
- 第一行是
error:或warning:加上错误本身:有一个找不到的变量ab。 main.typ:1:1是文件、行号和列号。命令行版的列号从 0 开始数,所以1:1是第 1 行的第二个字符。- 下面是出错的那一行源码,
^标出 Typst 认为出错的那一段。 hint:是 Typst 给出的改法建议,常常可以照做。
和 LaTeX 相比,有几点不同:
- 有错误就不生成 PDF。 LaTeX 遇到某些错误后还能排出 PDF;Typst 只要有一条
error,这次编译就没有新的 PDF;只有warning时 PDF 照常生成。 - 改好一条,可能冒出下一条。 语法错误(括号不配对之类)会一起列出,这时 Typst 不再往下执行代码;执行代码时遇到第一个错误也会停下,后面的错误要等它改好才会出现(标签找不到这类引用错误例外,会一起列出)。所以从第一条改起,改一条看一次。
- 引用不需要多编译几次。
@标签在一次编译里就能填好编号,不会出现 LaTeX 那样第一次显示??的情况;Typst 报引用错误时,问题就在源码里,再编译一次也不会消失。
在 JointTex 里,Typst 项目边写边编译,不需要点编译按钮。出错的那一段会在源码里画上波浪线,错误和警告同时列在"问题"标签页里,Typst 给出的 hint 也附在后面。改好之前,PDF 预览保持上一次编译成功的结果,所以写到一半时 PDF 没变,先看"问题"里有没有错误。服务器上的编译使用同样的 Typst 0.15.1,报错的文字相同(宏包找不到时例外,见下文)。本文引用报错时省略了部分 hint,例如只适用于命令行的 --root 提示。
unknown variable:名字找不到
error: unknown variable: tabel
原因:
- 函数名拼错了,如
#tabel(...)、#imgae(...); - 函数来自宏包,但没有导入。比如用了 cuti 的
#fakebold却没写#import "@preview/cuti:0.4.0": fakebold,报unknown variable: fakebold; - 变量在使用之后才用
#let定义,或者定义在[...]、{...}块里,块外看不到。
公式里最常见。 在 $...$ 里,连写的字母是一个名字:$ab$ 报 unknown variable: ab,相乘要写 $a b$;$v_平均$ 报 unknown variable: 平均,文字要放在引号里,$v_"平均"$;$mathbf(v)$ 报 unknown variable: mathbf,Typst 写 upright(bold(v))。
从 LaTeX 粘贴公式时,报错的名字常常少了第一个字母:
error: unknown variable: rac
┌─ main.typ:1:6
│
1 │ 分数 $\frac{a}{b}$。
│ ^^^
Typst 公式里的反斜杠是转义符,\f 被当成一个转义的字母 f,剩下的 rac 成了变量名。同样,\sum 报 unknown variable: um。去掉反斜杠,并把花括号换成 Typst 的写法:a/b 或 frac(a, b),sum_(i=1)^n。只删反斜杠、留下花括号不会报错,但花括号会原样印在公式里。Typst 公式的完整写法见 Typst 数学公式。
// title: 修好的 Typst 公式写法
#set text(font: ("Libertinus Serif", "Noto Serif CJK SC"), lang: "zh", region: "cn")
// 公式里的汉字用简体中文字体
#show math.equation: set text(font: ("New Computer Modern Math", "Noto Serif CJK SC"))
// 从 LaTeX 粘贴过来的公式,常见的几处改法:
// 错误写法:$\frac{a}{b}$ → unknown variable: rac(\f 被当成转义,剩下 rac)
// Typst 的分数写成 a/b 或 frac(a, b),不要反斜杠,参数用圆括号和逗号
$ a/b + frac(1, 2) $
// 错误写法:$ab$ → unknown variable: ab
// 连写的字母是一个变量名;表示相乘时中间加空格
$ a b + 2 x y $
// 错误写法:$v_平均$ → unknown variable: 平均
// 公式里的文字写在双引号里,相当于 LaTeX 的 \text{}
$ v_"平均" = s/t $
// 错误写法:$mathbf(v)$ → unknown variable: mathbf
// 直立粗体写 upright(bold(v));只写 bold(v) 得到的是粗斜体
$ upright(bold(v)) = (v_1, v_2) $
// 错误写法:$\sum_{i=1}^{n} x_i$ → unknown variable: um(\s 同样被当成转义)
// 去掉反斜杠写成 sum_{i=1}^{n} 不报错,但花括号会原样印出来;分组要用圆括号
// 常用的名字(sum、alpha、infinity)前面都不加反斜杠
$ sum_(i = 1)^n x_i quad alpha + beta quad x -> infinity $
// 错误写法:$ x = (a + b $ → 不报错,但括号不配对,排出来就少半边
$ x = (a + b) $
// 正文里的美元符号要转义,否则会被当成公式的开头:
价格 \$5,折后 $5 times 0.8 = 4$ 美元。
unclosed delimiter:括号或标记没有闭合
error: unclosed delimiter
┌─ main.typ:1:16
│
1 │ #text(fill: red)[红色
│ ^
^ 指向的是没有闭合的那个开头,不是应该补上结尾的地方。常见的情形:
(、[、{少了对应的右括号;*加粗或_强调只写了开头的*或_,这时^指向那个星号或下划线;- 正文里的美元符号:
价格 $5中的$被当成公式的开头,一直找不到结尾。要印出美元符号,写\$5。
反过来,多出一个右方括号会报 unexpected closing bracket,并提示 try using a backslash escape: \]。
expected expression 等语法错误
# 后面要紧跟代码。Typst 读到 # 却找不到表达式,就报 expected expression:
error: expected expression
┌─ main.typ:1:1
│
1 │ # 引言
│ ^
这多半是把 Markdown 的标题写法带了过来,Typst 的标题是 = 引言。参数写了名字没写值,如 #set text(size: ),也报这个错。
同类的语法错误还有:
| 写法 | 报错 | 改法 |
|---|---|---|
#figure(image("a.png") caption: [图]) | expected comma | 参数之间加逗号 |
#table(columns: 2, [a], , [b]) | unexpected comma | 删掉多余的逗号 |
#set text(lang:"zh") | the character `:` is not valid in code | 代码里用半角冒号 |
#set text(lang: "zh",size: 12pt) | the character `,` is not valid in code | 代码里用半角逗号 |
中文输入法下最容易出最后两种:代码只认半角标点。
类型错误:cannot add、expected length
Typst 的值有类型,数字、长度、字符串、内容不能随便混用:
error: cannot add string and integer
┌─ main.typ:2:2
│
2 │ #("共 " + n + " 章")
│ ^^^^^^^^^
字符串不能和整数相加,先用 str(n) 转成字符串;或者直接在正文里写 共 #n 章。
长度要带单位:
error: expected length, found integer
┌─ main.typ:1:16
│
1 │ #set text(size: 12)
│ ^^
│
= hint: a length needs a unit - did you mean 12pt?
把长度写成字符串,如 size: "12pt",报 expected length, found string,去掉引号即可。其他常见的几条:
unexpected argument: widht:参数名拼错,或者这个函数没有这个参数。查文档里该函数的参数列表。missing argument: body:少了必需的参数,如#heading(level: 2)没写标题文字,应为#heading(level: 2)[标题]。
忘了写 #:代码原样印了出来
text(fill: red)[红字] 和 set text(size: 14pt)
这一行不报错,PDF 里会原样出现 text(fill: red)[红字] 这些字。在正文里调用函数、写 set 规则,都要以 # 开头:#text(fill: red)[红字]、#set text(size: 14pt)。在 # 开始的代码里(比如函数的参数中)调用别的函数不用再写 #,如 #text(fill: red, strong[红字]);但方括号 [...] 里又回到了正文,要重新写 #。
正文里还有几个字符有特殊含义,用错了不一定报错,但结果不对:
@开始一个引用。邮箱[email protected]会报label `<example.com>` does not exist in the document,要写成zhang\@example.com。<abc>是一个标签,不报错,直接从 PDF 里消失。要印出尖括号,写\<abc\>。//是注释,从它开始到行尾的内容都不会出现在 PDF 里,也不报错;网址里的//不受影响。#、$、*、_要原样印出时同样加反斜杠。单词中间的下划线(data_2026.csv)不会变成强调,可以不转义。
set 规则只影响它后面的内容。 #set text(fill: blue) 写在第二段之前,第一段不会变色;写在 #[ ... ] 块里的 set 规则只在这一块里有效。设置写在文档中间却"对前面没起作用",就是这个原因。整篇文档的设置应放在开头。
// title: 修好的 Typst 标记与代码
#set text(font: ("Libertinus Serif", "Noto Serif CJK SC"), lang: "zh", region: "cn")
#set heading(numbering: "1.")
= 正文里的特殊字符
// $ 开始公式,@ 开始引用,< > 写标签,* 和 _ 表示加粗和强调,# 进入代码
// 要原样印出,在前面加反斜杠
// 错误写法:价格 $5 → unclosed delimiter;[email protected] → label `<example.com>` does not exist
价格 \$5,邮箱 zhang\@example.com,编号 \#1,尖括号 \<abc\>,星号 \*,下划线 \_。
// 单词中间的下划线不会变成强调,可以直接写
文件名 data_2026_v2.csv 不需要转义。
// // 是注释:从它开始到行尾的内容不会出现在 PDF 里,也不报错
// 要印出两个斜杠,写成 \/\/;网址里的 // 不受影响,Typst 会把整个网址识别成链接
两个斜杠 \/\/ 要转义,网址 https://typst.app/docs 可以直接写。
= 函数前面的 \#
// 在正文里调用函数要以 # 开头;漏写 # 时不报错,函数名和括号会原样印出来
// 错误写法:text(fill: red)[红字]
#text(fill: red)[红字]、#strong[加粗]、#underline[下划线]。
// 代码里只能用半角标点
// 错误写法:#set par(justify:true) → the character `:` is not valid in code
#set par(justify: true)
= set 规则的位置
// set 规则只影响它后面的内容,写在前面的段落不受影响
这一段是黑色的。
#set text(fill: blue)
这一段是蓝色的。
// 放在 #[ ] 里的 set 规则只在这一块里有效
#[
#set text(fill: green)
这一段是绿色的。
]
块后面又是蓝色。
unknown font family:字体找不到(警告)
warning: unknown font family: simsun
┌─ main.typ:1:16
│
1 │ #set text(font: "SimSun")
│ ^^^^^^^^
这是警告,PDF 照常生成,但文字用的是别的字体。注意报告里的字体名一律是小写,和源码里的写法不同,不代表大小写写错了;Typst 匹配字体名本身就不区分大小写。
找不到指定的字体时,Typst 从其他字体里找能显示这些字的,找到的不一定是想要的那种:用 JointTex 页面上的字体编译时,SimSun 找不到后,汉字用的是 Noto Serif CJK 的日文字形。所以应当写出编译环境里确实有的字体名,比如 "Noto Serif CJK SC"。服务器上的编译环境还有更多中文字体,在服务器上编译时,项目根目录下 fonts/ 文件夹里的字体文件也能用。中文字体的设置见 Typst 中文排版。
file not found:文件找不到
error: file not found (searched at figs/plot.png)
括号里是 Typst 实际去找的路径。在 JointTex 页面中编译时,它是从项目根目录算起的路径;在命令行里则是完整的绝对路径。对照这个路径检查:
- 路径相对于写这行代码的
.typ文件,而不是相对于主文件。chapters/intro.typ里写image("figs/plot.png"),Typst 找的是chapters/figs/plot.png。要从项目根目录算起,在路径前加/:image("/figs/plot.png")。 - 文件名的大小写要完全一致,
Plot.png和plot.png是两个文件。 - 图片、
#include的章节、.bib文件找不到,都是这条报错。
另外两条和路径有关的报错:
path `"../outside.png"` would escape the project root:用..跑到了项目根目录之外。Typst 只能读项目里的文件,把文件上传到项目里再引用。path must not contain a backslash:路径里用了反斜杠,如"figs\\plot.png"。从 0.15 起只能用/分隔目录,提示里会给出改好的路径。
label does not exist:标签或文献键不存在
error: label `<fig:polt>` does not exist in the document
@fig:polt 找不到对应的标签。检查拼写,以及标签是否写在了被引用的元素后面(#figure(...) <fig:plot>、$ ... $ <eq:a>、= 标题 <sec:a>)。
@ 后面紧跟汉字时,汉字会被算进标签名:由@eq:a得 报 label `<eq:a得>` does not exist in the document。在标签名后面留一个空格;后面是中文标点时不用。
引用参考文献时,键名在 .bib 里找不到,@键名 报的也是这条 label ... does not exist;写成 #cite(<键名>) 时报:
error: citation key `zhang2002` is not present in the bibliography
检查键名的拼写和大小写(Zhang2020 和 zhang2020 不同),以及 #bibliography(...) 是否指向了正确的 .bib 文件。文档里根本没有 #bibliography 时,#cite 报 the document does not contain a bibliography。参考文献的设置见 Typst 参考文献。
和引用有关的另外几条:
| 报错 | 原因 | 改法 |
|---|---|---|
cannot reference heading without numbering | 标题没有编号,无法引用 | #set heading(numbering: "1.") |
cannot reference equation without numbering | 公式没有编号 | #set math.equation(numbering: "(1)") |
label `<intro>` occurs multiple times in the document | 同一个标签用了两次 | 改成不同的名字 |
// title: 修好的 Typst 引用、文献与文件路径
#set text(font: ("Libertinus Serif", "Noto Serif CJK SC"), lang: "zh", region: "cn")
// 引用标题或公式之前要先打开编号
// 否则 @标签 报 cannot reference heading without numbering
#set heading(numbering: "1.")
#set math.equation(numbering: "(1)")
= 文件路径 <sec:path>
// 路径相对于当前 .typ 文件所在的目录;以 / 开头则从项目根目录算起
// 大小写要和文件名完全一致;目录分隔符只能用 /,写反斜杠会报 path must not contain a backslash
// 路径用 .. 跑到项目根目录之外会报 would escape the project root
#figure(
image("plot.svg", width: 50%),
caption: [示意曲线],
) <fig:plot>
= 标签与引用
// 标签写在被引用的元素后面;引用的名字要和标签一字不差
// 错误写法:@fig:polt → label `<fig:polt>` does not exist in the document
// 汉字也能做标签名,所以 @标签 后面紧跟汉字时要留一个空格,否则汉字会被算进标签名;后面是中文标点则不用
@fig:plot 是一条示意曲线,@sec:path 说明了路径的写法。
$ E = m c^2 $ <eq:energy>
由@eq:energy 可知,能量与质量成正比。
= 参考文献
// @键名 在文献库里找不到时,报的也是 label ... does not exist in the document
// 写成 #cite(<键名>) 时,报 citation key ... is not present in the bibliography
// 文献库里的键名区分大小写
Typst 的设计见 @zhang2020,TeX 的设计见 #cite(<knuth1984>)。
#bibliography("refs.bib", style: "gb-7714-2015-numeric")
宏包找不到或版本不对
Typst Universe 上的宏包用 #import "@preview/名字:版本" 导入,JointTex 会自动下载。三种常见的报错:
| 写法 | 报错 |
|---|---|
"@preview/no-such-pkg-xyz:0.1.0" | package not found (searched for @preview/no-such-pkg-xyz:0.1.0) |
"@preview/cuti:0.9.0" | package not found (searched for @preview/cuti:0.9.0) |
"@preview/cuti" | package specification is missing version |
前两种在 JointTex 的编辑页面里报的是同一条 package not found:要么宏包名拼错了,要么这个版本不存在。到 Typst Universe(typst.app/universe)上核对名字和版本号。项目改在服务器上编译时,这两种情况报的是 failed to download package。在自己电脑上用 Typst 命令行编译时,版本不存在会报 package found, but version 0.9.0 does not exist (latest is 0.4.0),括号里是当时最新的版本。第三种是没写版本号,Typst 要求写明完整的版本。宏包导入成功、但冒号后面的函数名写错(如 : fakebld)时,报 unresolved import。
本文的修正版示例可以在 JointTex 中一键打开为新项目,可以在其中故意改错,对照"问题"标签页观察每种报错。
