跳转到内容

错误信息

本页列出为 etemenanki-app 或 katana 编写配置时会遇到的错误:每条消息说了什么、由什么引起、应当改哪里。内容按出错的配置部分分组,你可以直接在本页搜索终端里显示的文字。

本页的每条消息都是 etemenanki 2.0.2(其中的 etemenanki-app 仍报告版本 2.0.0)与 katana 3.0.1 实际打印的文本,已对照源码核实,并通过对小型错误配置文件运行 --test 采集。某条消息只会在启动或重载时出现的,本页会特别说明。消息中的 <tag> 代表入站、出站或负载均衡器的 tag,<value> 代表你填写的值,<path> 代表文件路径,<error> 代表底层错误的文本,<id> 代表 katana 节点的 api.node_id,<name> 代表 katana 重载日志行使用的节点名称(<panel>@<host>#<id>[/<type>],见 katana 重载失败),<N> 代表秒数。其余部分均按原样打印。

两个程序都会在打开任何 socket 之前构建完整的配置,并在遇到第一个错误时停止。修复它,再次运行 --test,重复这一过程直到文件通过检查。检查顺序见命令行:etemenanki-app 依次为解析、至少一个出站、DNS、出站、负载均衡器、路由、入站;katana 依次为解析、DNS 与出站、至少一个节点、然后逐个检查节点。

无论出现在哪里,消息本身都相同,变化的只是前面的前缀。

场景 etemenanki-app 前缀 katana 前缀
--test configuration invalid: ,位于一条 ERROR 日志行中,输出到标准输出 configuration error: ,输出到标准错误
启动 failed to start: failed to load config: (读取或解析)、failed to build outbounds: ([dns] 或 [[outbound]])、node <id>: (面板类型或节点类型)、node <id>: build router: (路由)
节点启动(仅 katana) node <id>: initial start failed: <error>; retrying in <N>s,其他重试原因的形式相同(见节点启动期间的重试);之后为 node <id>: rebuild failed:
重载 reload: parse failed, keeping current config: 、reload: build failed, keeping current config: config reload failed, keeping current: 、reload: bad outbounds, keeping current config: 、reload: node <name>: <error>; keeping current config、node <id>: config edit refused, keeping the running one: ,以及 [[outbound]] 变更之后的 node <id>: route rebuild failed, keeping current:

无论在哪里出现,katana 还会在每个 TOML 错误前加上 config parse error: ,在编码错误前加上 config not utf-8: ,因此启动时你看到的是 failed to load config: config parse error: …。在 --test 下,它会在 Hysteria 2 节点的错误前加上 node <id>: 。

TOML 错误会占据多行。它给出行号和列号,引用出错的那一行,最后给出原因:

$ etemenanki-app --test -c config.toml
2026-09-25T03:57:12.004118Z ERROR etemenanki_app: configuration invalid: TOML parse error at line 8, column 1
|
8 | prot = 1080
| ^^^^
unknown field `prot`, expected one of `tag`, `protocol`, `listen`, `port`, `stream`, `address_family`, `sniffing`, `settings`

大多数消息会指出它涉及的入站、出站或节点。下面这些消息不会,你只能根据它们引用的值找出原因,或者逐段注释掉配置再运行 --test:

  • 操作系统错误,例如 No such file or directory (os error 2) 和 Permission denied (os error 13)。它们可能来自配置中指定的任何文件:配置文件本身、cert_file、key_file、ca_file、[dns].ca_file、geoip 和 geosite。消息中不打印路径;
  • OpenSSL 错误,以 error: 加一个代码开头,以及相关的 no certificate in PEM bundle 和 no certificate in CA PEM bundle;
  • Shadowsocks 2022 密钥错误:decode PSK: … 和 shadowsocks-2022: …;
  • 来自 Hysteria 2 用户表或证书的错误,以 hysteria2: 开头;
  • unknown vmess security "<value>"、unknown balancer strategy "<value>" …、a balancer needs at least one outbound 和 wireguard cannot be used as an inbound (no server implementation);
  • 所有路由错误。它们会引用值或 tag,但不指明是哪条规则。

构建任何内容之前,会先解析整个文件。每个表都会拒绝它不认识的键,因此拼写错误会让代理停止,而不是被忽略。

消息 含义 修复
TOML parse error at line <n>, column <m>,后跟 unknown field `<key>`, expected one of … 键名拼错了,或者键放在了一个没有该键的表里。列表给出该表接受的键。 改正键名。如果键名没错,检查它位于哪个表中(见下文)。
missing field `<key>` 缺少必需的键:[[inbound]] 和 [[outbound]] 中的 tag 或 protocol,[[route.rule]] 中的 outbound,[[balancer]] 中的 tag 或 outbounds。 添加该键。
invalid type: string "<value>", expected u16 数字被写在了引号里,例如 port = "1080"。 去掉引号。
invalid value: integer `<n>`, expected u16 数字超出范围,例如 port = 70000。 使用 0 到 65535 之间的值。
invalid type: string "<value>", expected a boolean sniffing 之类的开关被写成了字符串。 写成不带引号的 true 或 false。
duplicate key [dns] 或 [route] 之类的表出现了两次,或者同一个表中某个键出现了两次。 把两者合并为一个。
unclosed array table, expected `]]`、unclosed table, expected `]`、string values must be quoted, expected literal string、… TOML 本身在报告的位置格式错误。 修正所示行、列处的语法。
invalid utf-8 sequence of <n> bytes from index <i> 文件不是 UTF-8 编码,例如被保存为 UTF-16 或旧式代码页。 将文件保存为 UTF-8。
No such file or directory (os error 2)、Is a directory (os error 21) -c 指定的路径不存在,或者是一个目录。 传入正确的路径。相对路径以工作目录为基准解析。
config defines no outbounds 文件中没有 [[outbound]]。空文件也会这样失败。 至少添加一个出站。第一个出站就是默认路由。

[inbound.settings] 和 [outbound.settings] 表在文件解析完成、协议确定之后才检查。因此它们的错误带的是 tag,而不是行号。

消息 含义 修复
inbound <tag>: invalid settings: unknown field `<key>`, expected one of … settings 表中有该协议不接受的键。列表给出接受的键。 改正或删除该键。各协议页面列出了所有键。
inbound <tag>: invalid settings: missing field `<key>` 缺少必需的设置,例如 Trojan 用户的 password。如果存在外层键,第二行 in `users` 会指出它。 添加该键。
inbound <tag>: invalid settings: invalid type: … 某个设置的类型不对。第二行(例如 in `udp` )会指出是哪个。 使用协议页面给出的类型。
outbound <tag>: invalid settings: … 出站的同样三种错误。 同上。

这些错误来自 [dns]。katana 自己的 [dns] 表也打印相同的消息。

消息 含义 修复
dns: unknown backend "<value>" (expected "system", "udp", "tls" or "https") backend 不是这四个名称之一。不接受 "doh" 和 "dot"。 DNS over HTTPS 用 "https",DNS over TLS 用 "tls"。
dns: the udp backend needs a server address(tls、https 同理) 除 system 外,每种 backend 都需要 server。 添加 server = "<ip>:<port>"。
dns: invalid server address: invalid socket address syntax server 不是带端口的 IP 地址。主机名或不带端口的 IP 都会被拒绝。 写成 "192.0.2.53:53" 或 "[2001:db8::53]:853"。
dns: the tls backend needs a server name to verify against backend = "tls" 但没有 server_name。 添加解析器证书上的名称。
dns: the https backend needs the resolver's url backend = "https" 但没有 url。 添加 url,例如 "https://dns.example.com/dns-query"。
dns: "<url>" is not an https:// url url 不以 https:// 开头。 使用 https:// 形式。
dns: "<url>" has no usable host url 中没有主机,或主机前带有用户名(user@)。 去掉用户名部分,保留主机。
No such file or directory (os error 2) ca_file 指向的文件不存在。无论哪种 backend(即使是 system)都会读取该文件。 修正路径,或删除 ca_file。
no certificate in CA PEM bundle ca_file 中没有 PEM 证书(backend 为 tls 和 https 时)。 指向至少包含一个 BEGIN CERTIFICATE 块的 PEM 文件。

这些错误来自 [inbound.stream]、[outbound.stream] 及其 tls、ws、grpc 子表。前缀为 inbound <tag>: 或 outbound <tag>: 。

前缀之后的消息 含义 修复
security = "tls" is not valid with network = "tcp"; use network = "tls" for TLS over plain TCP (security = "tls" layers TLS under network = "ws" or "grpc") 这是 Xray 对 TLS over TCP 的写法。在这里,TLS over TCP 是一种独立的 network。 把这两个键替换为 network = "tls"。
unknown stream security "<value>" (expected "tls" or "none") security 既不是 "tls" 也不是 "none"。该值区分大小写,不支持 "reality" 和 "xtls"。 写小写的 "tls" 或 "none"。
unknown stream network "<value>" network 不是 tcp、tls、ws 或 grpc。不支持 "h2"、"http"、"quic" 和 "kcp"。 从这四种 network 中选择一种。
grpc stream needs grpc.service_name network = "grpc" 但没有 [….stream.grpc] service_name。 添加服务名。两端必须一致。
protocol <name> does not support stream network "<value>" 该协议没有自己的传输层:SOCKS 和 Shadowsocks 入站、Hysteria 2 和 TUN,以及 freedom、blackhole、wireguard 和 hysteria2 出站。 删除 [….stream] 表。
protocol <name> does not support stream security "<value>" 同上,针对 security。 删除 [….stream] 表。
tls stream needs tls.cert_file 入站使用了 TLS(network = "tls",或在 ws、grpc 下设置 security = "tls"),但没有证书。 在 [inbound.stream.tls] 下添加 cert_file。
tls stream needs tls.key_file 同上,针对私钥。 添加 key_file。
tls stream needs tls.server_name or server(ws+tls 和 grpc+tls 同理) 使用 TLS 的出站既没有 server_name 也没有 server,无法据此校验证书。 设置 server,或在 [outbound.stream.tls] 下设置 server_name。
ws stream needs ws.host or server WebSocket 出站没有可用于 Host 头的主机。 设置 server、tls.server_name 或 ws.host。
grpc stream needs grpc.authority or server gRPC 出站没有 authority。 设置 server、tls.server_name 或 grpc.authority。
tls.allow_insecure and tls.ca_file cannot both be set 这两个键相互矛盾。 信任私有 CA 时保留 ca_file,跳过校验时保留 allow_insecure,不要同时设置。

证书文件产生的错误不带前缀:

消息 含义 修复
No such file or directory (os error 2) cert_file、key_file 或 ca_file 在该路径下不存在。 修正路径。相对路径以工作目录为基准解析。
Permission denied (os error 13) 进程无权读取该文件,通常是私钥。 给服务用户授予读取权限。
no certificate in PEM bundle cert_file 中没有 PEM 证书。 指向证书链,叶子证书在前。
no certificate in CA PEM bundle 出站的 ca_file 中没有 PEM 证书。 指向 CA 证书。
error:1E08010C:DECODER routines:…:No supported data to decode. Input type: PEM key_file 中没有 PEM 私钥。具体的 OpenSSL 文本随 OpenSSL 版本而不同。 指向未加密的 PEM 私钥。
error:0A0000BE:SSL routines:SSL_CTX_check_private_key:no private key assigned:… 私钥与证书不匹配。 使用与该证书一同生成的私钥。

前缀为 inbound <tag>: 。

前缀之后的消息 含义 修复
port is required 监听 IP 地址的入站没有 port。 添加 port。
a unix socket listen has no port; remove port listen 以 / 开头,即 Unix socket 路径,但同时设置了 port。 删除 port。
abstract unix sockets are not supported; use a filesystem path listen 以 @ 开头。 使用文件系统路径,例如 /run/etemenanki/http.sock。
hysteria2 listens on UDP and cannot use a unix socket Hysteria 2 入站的 listen 是一个路径。 填写 IP 地址和端口。
socks over a unix socket has no local IP for UDP associate; set udp_bind or udp = false Unix socket 上的 SOCKS 入站仍然开启了 UDP(默认开启)。 设置 udp = false,或把 udp_bind 设为本机的某个 IP 地址,其地址族须与客户端发送数据报所用的源地址一致,例如本地 IPv4 客户端用 127.0.0.1。此后每个客户端的 UDP ASSOCIATE 都必须写明其数据报确切的源地址和端口。见在 Unix socket 上监听。
protocol <name> over a unix socket does not support stream network "<value>" Unix socket 入站带有 [inbound.stream] 表。Unix socket 不承载传输层。 删除 [inbound.stream] 表。
tun owns a network interface and has no listener; remove listen/port TUN 入站设置了 listen 或 port。 两者都删除。
tun mtu must be at least 1280 TUN 的 mtu 低于 IPv6 的最小值。 使用 1280 或更大的值。
bad tun address "<value>": <error> address 中的某项不是 IP 地址(带或不带前缀长度)。 写成 "198.18.0.1/15" 或 "198.18.0.1"。
bad tun route "<value>": host part of address was not zero 某条路由的主机位不为零,例如 "198.18.0.1/15"。 写网络地址:"198.18.0.0/15"。

--test 不绑定任何端口,因此下列错误只在启动(failed to start: …)或重载时出现:

消息 含义 修复
inbound <tag> bind <bind> failed: Address already in use (os error 98) 另一个程序,或同一文件中的另一个入站,占用了该端口。两个入站使用同一端口能通过 --test。 释放端口或更换端口。
inbound <tag> bind <bind> failed: Permission denied (os error 13) 在没有相应权限的情况下使用了 1024 以下的端口。 授予 CAP_NET_BIND_SERVICE,或使用更高的端口。
inbound <tag> bind <bind> failed: Cannot assign requested address (os error 99) listen 不是本机的地址。 使用本机拥有的地址,或 0.0.0.0。
inbound <tag> bind unix:<path> failed: <path> exists and is not a socket Unix socket 路径已被普通文件或目录占用。残留的旧 socket 会被替换,其他文件则保持不动。 删除该文件,或另选路径。
inbound <tag> bind tun auto failed: Operation not permitted (os error 1) 创建 TUN 设备需要 CAP_NET_ADMIN。设置了 name 时,tun auto 会变成 tun <name>。 以 CAP_NET_ADMIN 运行。见 TUN。

<bind> 对 TCP 为 <host>:<port>,对 Hysteria 2 为 udp <host>:<port>,对 Unix socket 为 unix:<path>,对 TUN 为 tun <name>。

能通过 --test 的 SOCKS 入站,仍可能在客户端请求 UDP ASSOCIATE 时拒绝。此时入站以 SOCKS5 应答 0x02(规则集不允许连接)回复,关闭控制连接,并以 debug 级别记录原因。在这些日志行中,<source> 在 TCP 上为 Some(<ip>),即客户端的地址,在 Unix socket 上为 None。

日志行 含义 修复
socks connection from <source> ended: socks: UDP associate from an address family the relay is not bound in 中继永远收不到该客户端的数据报,因此入站直接拒绝这个 UDP 关联,而不是让它悄无声息地失效。IPv4 的 udp_bind,或 IPv4 映射的 IPv6 地址(例如 ::ffff:192.0.2.10),只能接收 IPv4 客户端;:: 两者都能接收;其他 IPv6 的 udp_bind 只能接收 IPv6 客户端。例如 udp_bind = "127.0.0.1",而客户端通过 ::1 连接。在 Unix socket 上,地址族取客户端请求中写明的地址。 把 udp_bind 设为客户端连接所用的地址族,或为每个地址族各运行一个入站。
socks connection from None ended: socks: UDP associate over a unix socket must name its source address and port Unix socket 上的客户端发送的 UDP ASSOCIATE 写的是全零地址、零端口或域名。在 TCP 上,入站把 UDP 关联限定在控制连接的地址上,但 Unix socket 没有这样的地址,只能依据请求本身。RFC 1928 允许客户端在不知道自己地址时填零,很多客户端都这样做,包括 etemenanki-app 自己的 SOCKS 出站。 让客户端写明它发送数据报时确切的源地址和端口,或设置 udp = false。见 UDP ASSOCIATE。
消息 含义 修复
inbound <tag>: unknown protocol "<value>" 不是入站协议。入站协议有 socks、http、trojan、vless、vmess、shadowsocks、hysteria2(也可写 hysteria、hy2)和 tun。 改正名称。名称为小写。
outbound <tag>: unknown protocol "<value>" 不是出站协议。出站协议有 freedom(也可写 direct)、blackhole(也可写 block)、socks、http、trojan、vless、vmess、shadowsocks、hysteria2(也可写 hysteria、hy2)和 wireguard。 改正名称。
wireguard cannot be used as an inbound (no server implementation) WireGuard 只能用作出站。 只在 [[outbound]] 中使用 WireGuard。
outbound <tag>: missing server 代理出站没有 server。 添加上游的主机名或 IP 地址。
outbound <tag>: missing port 代理出站没有 port。 添加上游端口。
inbound <tag>: unknown socks auth "<value>" auth 不是 "none" 或 "password"。 使用二者之一。
inbound <tag>: invalid uuid "<value>": <error> VLESS 或 VMess 用户的 id 不是 UUID。 使用 36 个字符的形式,例如 11111111-2222-3333-4444-555555555555。
outbound <tag>: invalid uuid "<value>": <error> 同上,针对出站的 id。 同上。
unknown vmess security "<value>" VMess 出站的 security 不是 auto、aes-128-gcm 或 chacha20-poly1305(不区分大小写)。消息中的值以小写显示。 使用这三者之一,或省略它以使用 aes-128-gcm。
inbound <tag>: unknown shadowsocks method "<value>"(outbound 同理) 不是受支持的 method:aes-128-gcm、aes-256-gcm、chacha20-poly1305(也可写 chacha20-ietf-poly1305)、xchacha20-poly1305(也可写 xchacha20-ietf-poly1305),不区分大小写,或者 2022- 系列 method。不支持 rc4-md5 等流加密算法。 使用受支持的 AEAD method。
inbound <tag>: unknown shadowsocks-2022 method "<value>"(outbound 同理) 以 2022- 开头,但不是 2022-blake3-aes-128-gcm、2022-blake3-aes-256-gcm 或 2022-blake3-chacha20-poly1305 的 method。 改正名称。这三个名称区分大小写。
decode PSK: <error> Shadowsocks 2022 的密码不是标准 base64。 使用 base64 密钥,例如由 openssl rand -base64 32 生成。
shadowsocks-2022: PSK too short (<n> < <len>) 解码后的密钥字节数少于 method 的要求:2022-blake3-aes-128-gcm 需要 16 字节,另外两个需要 32 字节。 生成长度正确的密钥:openssl rand -base64 16 或 openssl rand -base64 32。
shadowsocks-2022: multi-user requires an aes-gcm method 带 users 的 Shadowsocks 2022 入站使用了 2022-blake3-chacha20-poly1305。 多用户时使用 aes-gcm 系列 method。
outbound <tag>: invalid address_family "<value>" 不是 auto、ipv4_only、ipv6_only、prefer_ipv4 或 prefer_ipv6。也接受 ipv4、v4、4 及对应的 IPv6 写法,不区分大小写,并允许用 - 代替 _。 使用上述值之一。
消息 含义 修复
duplicate outbound tag: <tag> 两个 [[outbound]] 使用了同一个 tag。 重命名其中一个。
duplicate inbound tag: <tag> 两个 [[inbound]] 使用了同一个 tag。 重命名其中一个。
balancer tag <tag> collides with an outbound tag 负载均衡器使用的 tag 已被某个出站或前面的负载均衡器占用。 给负载均衡器一个独立的 tag。
balancer <tag> references unknown outbound tag: <member> outbounds 中的某个名称不是出站 tag。负载均衡器不能包含另一个负载均衡器。 改正成员 tag。
balancer <tag>: outbound <member> has no upstream a TCP health probe can reach, so it cannot be balanced 健康探测是对成员的 server 和 port 发起 TCP 连接。该成员没有 server 和 port(freedom、blackhole 和 wireguard 出站通常没有),或者它是只监听 UDP 的 hysteria2。 只对具有 TCP 上游的代理出站做负载均衡。
unknown balancer strategy "<value>" (expected "failover" or "round_robin") strategy 是其他值。 使用 "failover"(默认)或 "round_robin"。
a balancer needs at least one outbound outbounds = []。 至少列出一个成员。

负载均衡器介绍了健康探测和各种策略。

路由错误不会指明是哪条规则。请在文件中搜索它们引用的值。inbound_tag 指向不存在的入站不算错误:该规则只是永远不会匹配。

消息 含义 修复
route references unknown outbound tag: <tag> 某条规则的 outbound 或 [route].default 指向的既不是出站也不是负载均衡器。 改正 tag。
invalid cidr "<value>": host part of address was not zero cidr 或 source_cidr 中的某项主机位不为零,例如 "192.0.2.1/24"。 写网络地址 "192.0.2.0/24";只匹配单个地址时写 "192.0.2.1/32"。
invalid cidr "<value>": invalid length for network: … 前缀长度过长,例如 IPv4 用了 /33。 IPv4 使用 /0 到 /32,IPv6 使用 /0 到 /128。
invalid cidr "<value>": couldn't parse address in network: invalid IP address syntax 该项根本不是地址,例如是主机名。 使用 IP 网段。匹配域名请用域名匹配条件。
invalid rule network "<value>" (expected "tcp" or "udp") network 是列表或其他词,例如 "tcp,udp"。 使用 "tcp" 或 "udp",或省略 network 以同时匹配两者。
invalid port spec: "<value>" port 中的某项不是数字,也不是 low-high 范围。"80,443" 这样的逗号列表和 "https" 这样的名称都会被拒绝。 每个端口或范围单独写一项:port = ["80", "443", "8000-9000"]。
TOML parse error … invalid type: integer `<n>`, expected a string port 中的某项写成了数字,例如 port = [443]。规则中的端口是字符串。 给每一项加上引号:port = ["443"]。
invalid port spec: "<value>" has a lower bound above its upper bound 类似 "443-80" 的范围。 把下界写在前面。
invalid domain regex "<value>": regex parse error: … domain_regex 中的某项无法编译。消息会延续多行,并指出问题所在。 修正正则表达式,或改用 domain_suffix 或 domain_full。
a geosite matcher is used but no geosite file is configured 规则使用了 geosite,但没有设置 [route].geosite。 把 [route].geosite 设为 geosite.dat 的路径。
a geoip matcher is used but no geoip file is configured 同上,针对 geoip。 设置 [route].geoip。
No such file or directory (os error 2) 该路径下不存在 geodata 文件。 修正路径。只有规则用到该文件时才会读取它。
geosite code not found: <code> geosite.dat 中没有这个列表名。Xray 的 geosite: 前缀不会被去掉,因此 "geosite:cn" 会这样失败。 只写名称本身,例如 "cn"。比较时不区分大小写。
geoip code not found: <code> 同上,针对 geoip.dat,包括带 geoip: 前缀的情况。 只写代码本身,例如 "cn" 或 "!cn"。
geosite decode: failed to decode Protobuf message: <error> 该文件不是 geosite .dat:文件被截断、是下载失败时得到的 HTML 错误页面,或者其实是 geoip 文件。 重新下载文件,并检查两个路径是否写反了。
geoip decode: failed to decode Protobuf message: <error> 同上,针对 geoip 文件。 同上。
geoip cidr: <error> geoip 文件可以解码,但规则所用列表中的某个网段格式错误:地址不是 4 或 16 字节,或者前缀长度超过地址长度。 更换 geoip 文件。

前缀为 outbound <tag>: 。

前缀之后的消息 含义 修复
invalid wireguard private_key 该密钥不是 32 字节的 base64 或 hex 编码。 粘贴 wg genkey 生成的密钥,或 wg-quick 文件中 PrivateKey 行的值。
invalid wireguard peer_public_key 同上,针对对端公钥。 使用对端 [Peer] 段中的 PublicKey。
invalid wireguard preshared_key 同上,针对预共享密钥。 使用 PresharedKey 的值,或删除该键。
wireguard endpoint must be host:port endpoint 中没有 :。 写成 "198.51.100.1:51820"。端口取最后一个 : 之后的部分,因此 IPv6 endpoint 不要加方括号:"2001:db8::1:51820"。
invalid wireguard endpoint port 最后一个 : 之后的部分不是端口号。 改正端口。
invalid settings: missing field `address` address 是必需的。 添加隧道地址,例如 address = ["10.0.0.2"]。
invalid settings: invalid IP address syntax,并带有 in `address` address 中的某项带有前缀长度,例如 "10.0.0.2/32"。该键只接受纯地址。 去掉 /32 或 /128。
invalid settings: invalid length <n>, expected an array of length 3,并带有 in `reserved` reserved 不是三个数字。 写三个字节,例如 reserved = [0, 0, 0],或删除该键。
wireguard address_family ipv6_only needs an IPv6 address(或 ipv4_only … IPv4) address_family 只允许一种地址族,而 address 中没有该地址族的地址。 添加该地址族的地址,或修改 address_family。

WireGuard 列出了每个键对应的 wg-quick 字段。

Hysteria 2 入站先检查证书,再检查用户,最后检查其余设置。带 inbound <tag>: 或 outbound <tag>: 前缀的消息连同前缀一起列出;其他消息打印时不带前缀。

消息 含义 修复
inbound <tag>: hysteria2 needs both cert_file and key_file [inbound.settings] 中缺少其中之一或两者。Hysteria 2 总是使用 TLS。 两者都设置。
hysteria2: the certificate file contains no certificates cert_file 中没有 PEM 证书。 指向证书链。
hysteria2: the key file contains no private key key_file 中没有 PEM 私钥。 指向私钥。
hysteria2: could not read the certificate: <error> cert_file 中的 PEM 已损坏。 更换该文件。
hysteria2: could not read the private key: <error> key_file 中的 PEM 已损坏。 更换该文件。
hysteria2: certificate and key do not match: <error> 私钥与证书不匹配。 使用匹配的私钥。
inbound <tag>: password and users cannot both be set; a credential would have two answers 同时配置了两种认证方式。 所有用户共用一个密码时保留 password,每个用户各有一项时保留 users。
inbound <tag>: hysteria2 needs password or users 两者都没有设置。 设置其中之一。
hysteria2: the password must not be empty password = ""。 设置密码。
hysteria2: a user needs both a name and a password users 中某项的 user 或 pass 为空。 两者都填写。
hysteria2: a username cannot contain ':' — it separates the two on the wire 某个 user 中包含 :。 选用不含冒号的用户名。
hysteria2: two users share a name once lower-cased 忽略大小写后,有两个 user 的值相同。 为它们取不同的名称。
inbound <tag>: hysteria2: 233 is the authentication success status and cannot be used for the masquerade masquerade.status = 233。 使用其他状态码,例如默认的 404。
inbound <tag>: hysteria2: <n> is not an HTTP status code masquerade.status 不在 100 到 999 之间。 使用真实存在的状态码。
inbound <tag>: obfs_password is set but obfs is not; did you mean obfs = "salamander"? 设置了 obfs_password 但没有设置 obfs。 添加 obfs = "salamander",或删除 obfs_password。
inbound <tag>: obfs_password must be at least 4 bytes for salamander obfs = "salamander",但 obfs_password 过短或缺失。 使用更长的密码。
inbound <tag>: unknown obfs "<value>" (expected "salamander") obfs 是其他值。该值区分大小写。 写 "salamander"。
inbound <tag>: udp_idle_timeout must be between 2 and 600 seconds 值超出范围。 使用 2 到 600,或省略它以使用 60。
inbound <tag>: udp_idle_timeout is set but udp is not enabled 设置了 udp_idle_timeout 但没有 udp = true。 设置 udp = true,或删除该超时设置。
inbound <tag>: max_connections must be at least 1(max_circuits 同理) 上限为 0。 使用正数,或省略它以使用默认值。

Hysteria 2 说明了每个键。

配置文件变化时,etemenanki-app 会先解析并构建新文件,然后才触及正在运行的配置。这些日志行来自 etemenanki_app::instance 日志 target,只有 config hot-reload disabled 来自 etemenanki_app。

日志行 发生了什么 应当怎么做
reload: cannot read <path>: <error> 无法读取文件。正在运行的配置保持不变。 修正文件路径或权限。
reload: parse failed, keeping current config: <error> 新文件解析失败。<error> 是上文的某个 TOML 错误。正在运行的配置保持不变。 修正文件后重新保存。
reload: build failed, keeping current config: <error> 新文件能解析,但构建失败。<error> 可以是本页的任何构建错误。正在运行的配置保持不变。 修正原因后重新保存文件。
inbound <tag> bind <bind> failed: <error> 新配置已替换旧配置,但这个入站无法绑定。其他入站正常运行,这个入站保持停止。 释放端口后重新保存文件。
config hot-reload disabled: <error> 启动时无法监视配置所在目录。代理照常运行,但在重启之前会忽略对文件的修改。 检查该目录是否存在且可读。

etemenanki-app 会记住它最后读取的文件内容(按字节),无论该文件是被应用还是被拒绝,都不会对相同的字节再试一次。如果原因在文件之外,例如证书缺失或端口被占用,只修复原因是不够的:还要修改一下配置文件,哪怕只改一个注释字符。重载的完整流程见 etemenanki-app 热重载。

katana 与 etemenanki-app 使用同一个内核,因此它的 DNS、出站键、路由和 Hysteria 2 消息往往与上文逐字相同。这一部分列出 katana 自己的消息,以及与上文不同的地方。

消息 含义 修复
config parse error: TOML parse error at line <n>, column <m> … 文件不是合法的 TOML,或者有未知键、类型错误。原因与 TOML 语法与未知键中的相同。 修正报告行上的键。
config parse error: … unknown field `ApiHost`, expected one of `host`, … 使用了 XrayR 的键名。katana 使用自己的蛇形命名(snake_case)键名。 重命名这些键。对照表见从 XrayR 迁移。
config not utf-8: invalid utf-8 sequence of <n> bytes from index <i> 文件不是 UTF-8 编码。 将文件保存为 UTF-8。
No such file or directory (os error 2) 配置文件、[dns].ca_file,或某条规则所需的 geodata 文件不存在。 修正路径。
config defines no [[node]] entries 文件中没有 [[node]]。空文件也会这样失败。 添加一个节点。
dns: … [dns] 无效。 见 DNS 解析器:消息完全相同。

启动时,解析错误记录为 failed to load config: <error>,[dns] 或 [[outbound]] 错误记录为 failed to build outbounds: <error>。两者都会让 katana 以状态码 1 退出。

消息 含义 修复
unknown panel_type "<value>" panel_type 缺失,或不是 NewV2board、V2board、SSPanel(不区分大小写)。消息中的值以小写显示,因此缺少该键时显示为 ""。 使用这三者之一。Xboard 面板使用 NewV2board。见 Xboard 与 V2board。
unknown node_type "<value>" api.node_type 缺失,或不是 V2ray、Vmess、Vless、Trojan、Shadowsocks、Hysteria2、Hysteria、Hy2(不区分大小写)。 使用面板上该节点的类型。

启动时这两条消息显示为 node <id>: unknown panel_type "<value>" 和 node <id>: unknown node_type "<value>"。katana 会跳过该节点,启动其他节点。如果没有任何节点剩下,它会记录 no nodes could be started 并以状态码 1 退出。重载时,同样的错误会让整次重载被拒绝:katana 记录 reload: node <name>: unknown panel_type "<value>"; keeping current config(或 unknown node_type),不应用任何内容(见 katana 重载失败)。

有两种组合能通过 --test,要到节点第一次联系面板时才会失败:

启动时的日志行 原因 修复
node <id>: node_info failed: sspanel: Shadowsocks node type is not supported; retrying in <N>s panel_type = "SSPanel" 且 node_type = "Shadowsocks"。 通过 Xboard 或 V2board 面板提供 Shadowsocks。
node <id>: node_info failed: sspanel: a hysteria2 node needs custom_config; the legacy server string cannot describe one; retrying in <N>s 以旧格式读取的 SSPanel Hysteria 2 节点:设置了 disable_custom_config = true,或者面板版本早于 2021.11。 为该节点使用 custom_config。见 SSPanel。

面板请求本身的错误,例如密钥或节点 ID 错误,见故障排查。

节点通过一次尝试上线:katana 先从面板读取节点,再读取其用户,然后启动监听器。某次尝试失败时,katana 会记录原因并再次尝试,因此面板正在重启、DNS 服务器尚未响应或端口仍被占用时,节点不会就此停在下线状态:

日志行 失败的环节
node <id>: node_info failed: <error>; retrying in <N>s 向面板请求节点信息。
node <id>: panel returned no node info; retrying in <N>s 面板以 304 Not Modified 响应了节点请求,没有返回节点。
node <id>: panel returned port 0; retrying in <N>s SSPanel 面板给出的节点端口为 0。在 Xboard 和 V2board 上,同样的问题显示为 node <id>: node_info failed: newV2board: server port must be > 0; retrying in <N>s。
node <id>: user_list failed: <error>; retrying in <N>s 向面板请求用户列表。
node <id>: panel returned no user list; retrying in <N>s 面板以 304 Not Modified 响应了用户请求,没有返回列表。
node <id>: initial start failed: <error>; retrying in <N>s 监听器未能启动,例如由于后面两节中的证书或节点设置问题。

第一次等待 1 秒。每失败一次等待时间翻倍,最多 60 秒,并且不会超过该节点的 update_periodic。重载应用了对该节点 [[node]] 表的修改时,katana 会立即重试,不再等待剩余的延迟。每次尝试都会重新向面板请求。节点上线之后,就不再以这种方式重试;之后的变更由常规轮询应用。

--test 只为 Hysteria 2 节点读取证书,因为其他节点是否使用 TLS 由面板决定。对其他所有节点类型,这些错误在节点启动时以 node <id>: initial start failed: <error>; retrying in <N>s 出现,或在变更之后以 node <id>: rebuild failed: <error> 出现。katana 只有在面板列出至少一个用户后才会构建监听器,因此没有用户的节点暂时不会报告这些错误。

消息 含义 修复
node requests kernel-unsupported feature: cert.reject_unknown_sni reject_unknown_sni = true。katana 没有实现它,并在每个节点上拒绝它,无论是否使用 TLS。 删除该键。
node requests kernel-unsupported feature: ACME cert mode "<mode>" mode 为 "dns"、"http" 或 "tls"。katana 没有 ACME 客户端。该检查适用于每个节点,无论是否使用 TLS。 使用 mode = "file",并自行续期证书。
TLS node requires cert.mode = "file" 面板开启了 TLS,而 mode 不是 "file"。默认值为 "none"。像 "files" 这样的未知 mode 能一直通过,直到遇到 TLS 节点才报错。 设置 mode = "file"。
TLS node requires cert.cert_file and cert.key_file mode = "file",但路径为空。 两个路径都设置。
No such file or directory (os error 2)、Permission denied (os error 13) 证书或私钥文件不存在或无法读取。消息中不打印路径。 检查两个路径和文件属主。
no certificate in PEM bundle,或以 error: 开头的 OpenSSL 消息 文件不是 PEM 证书和与之匹配的 PEM 私钥。见 stream 设置与 TLS。 更换这些文件。

对于同一个表,Hysteria 2 节点有自己的消息:

消息 含义 修复
hysteria2 node requires cert.mode = "file" Hysteria 2 节点没有设置 mode = "file",包括默认的 "none" 和各种 ACME mode。 设置 mode = "file",并配置 cert_file 和 key_file。
node requests kernel-unsupported feature: cert.reject_unknown_sni reject_unknown_sni = true。对 Hysteria 2 节点,--test 也会报告它。 删除该键。
TLS node requires cert.cert_file and cert.key_file 某个路径为空。 两者都设置。
hysteria2: the certificate file contains no certificates、hysteria2: the key file contains no private key、hysteria2: certificate and key do not match: <error> 与 etemenanki-app 的 Hysteria 2 入站相同。 更换这些文件。

有些设置来自面板,--test 无法检查。节点启动时,katana 会拒绝它没有实现的设置,而不是改为提供别的服务,并记录 node <id>: initial start failed: <error>; retrying in <N>s(变更之后则为 node <id>: rebuild failed: <error>)。katana 会一直重试,直到该设置发生变化,因此请在面板上改正它。

消息 含义 修复
node requests kernel-unsupported feature: REALITY 面板为该节点开启了 REALITY。 在面板上改用 TLS 或不加密。
node requests kernel-unsupported feature: VLESS XTLS flow 面板设置了 VLESS flow(例如 xtls-rprx-vision),或者以旧格式读取的 SSPanel 节点设置了 api.vless_flow。 在面板上清除 flow,或删除 api.vless_flow。
node requests kernel-unsupported feature: httpupgrade transport、… splithttp transport、… transport "<name>" 面板的 network 是 HTTPUpgrade、SplitHTTP 或 XHTTP,或者 katana 不认识的其他名称。katana 支持 TCP、WebSocket 和 gRPC。 在面板上更改该节点的 network。
node requests kernel-unsupported feature: shadowsocks cipher "<method>" 面板的 Shadowsocks method 不是受支持的 AEAD 或 2022- 系列 method。 在面板上选择受支持的 method。
node <id>: node_info failed: newV2board: shadowsocks obfs "<value>" is not supported; retrying in <N>s Xboard 或 V2board 的 Shadowsocks 节点设置了混淆插件。 为该节点关闭插件。

katana 的 [[outbound]] 采用扁平结构,uuid、method 等键直接写在表中。它的消息与 etemenanki-app 不同。

消息 含义 修复
duplicate/reserved outbound tag <tag> 两个出站使用了同一个 tag,或者 tag 是内置的 direct、block、freedom、blackhole 之一。 重命名该出站。规则始终可以使用内置 tag。
unknown outbound protocol "<value>" 不是 direct(也可写 freedom)、socks(也可写 socks5)、http、vmess、vless、shadowsocks(也可写 ss)或 wireguard(也可写 wg),不区分大小写。katana 没有 Trojan 和 Hysteria 2 出站。 使用受支持的协议。
outbound needs a non-empty server and non-zero port (got "<server>":<port>) 代理出站缺少 server 或 port。protocol = "blackhole" 的条目也会这样失败:请改用内置的 block tag。 添加 server 和 port。
outbound <tag> needs a uuid VMess 或 VLESS 出站没有 uuid。 添加它。
outbound <tag>: uuid is not a valid UUID uuid 无法解析。消息中不打印该值。 改正 UUID。
unsupported vmess security "<value>" security 不是 auto、aes-128-gcm(也可写 aes128gcm)或 chacha20-poly1305(也可写 chacha20poly1305),不区分大小写。不支持 none 和 zero。 使用其中之一,或省略它。
shadowsocks outbound <tag> needs a password Shadowsocks 出站没有 password。 添加它。
unsupported shadowsocks cipher "<value>" method 缺失或不是受支持的 method。katana 接受的 method 与 etemenanki-app 相同,未知的 2022- method 也以这条消息报告。 把 method 设为受支持的名称。
decode PSK: <error>、shadowsocks-2022: PSK too short (<n> < <len>) Shadowsocks 2022 密钥不是 base64,或者太短。 同入站与出站协议。
outbound <tag> invalid address_family "<value>" 同 etemenanki-app,只是 tag 后面没有冒号。 使用列出的值。
wireguard outbound <tag> needs a private_key(public_key 同理) 缺少必需的 WireGuard 密钥。对端的密钥在这里叫 public_key。 添加它。
wireguard outbound <tag> <field>: invalid WireGuard key: expected base64 or hex encoding of 32 bytes private_key、public_key 或 pre_shared_key 解码后不是 32 字节。 粘贴 wg genkey 或 wg pubkey 输出的密钥。
wireguard outbound <tag> needs at least one local_address 没有 local_address。 添加隧道地址。这里允许带 /32 之类的前缀长度。
wireguard outbound <tag> invalid local_address "<value>": <error> 某项不是 IP 地址。 改正它。
wireguard outbound <tag> address_family ipv6_only needs an IPv6 local_address(或 ipv4_only … IPv4) 没有 address_family 所要求地址族的 local_address。 添加一个,或修改 address_family。
wireguard outbound <tag> reserved must be exactly 3 bytes reserved 不是三项。 写三个 0 到 255 之间的数字。

katana 出站说明了每个键。

对于 node_type 为 Hysteria2、Hysteria 或 Hy2 的节点,--test 会让 [node.hysteria] 和证书经过与启动时相同的构建流程,只是不绑定端口。在 --test 下,消息带有前缀 node <id>: ;启动时则跟在 node <id>: initial start failed: 之后,并以 ; retrying in <N>s 结尾。

消息 含义 修复
unknown hysteria credential kind "<value>" (expected "uuid" or "user_pass") credential 是其他值。 使用 "uuid"(默认)或 "user_pass"。
obfs_password is set but obfs is not; did you mean obfs = "salamander"? 设置了 obfs_password 但没有设置 obfs。 添加 obfs = "salamander"。
obfs_password must be at least 4 bytes for salamander 混淆密码短于 4 字节。 使用更长的密码。
unknown obfs "<value>" (expected "salamander") obfs 是其他值。 写 "salamander"。
udp_idle_timeout must be between 2 and 600 seconds 超出范围。 使用 2 到 600。
udp_idle_timeout is set but udp is not enabled 设置了该项但没有 udp = true。 启用 udp,或删除该超时设置。
hysteria2: 233 is the authentication success status and cannot be used for the masquerade [node.hysteria.masquerade] status = 233。 选用其他状态码。
hysteria2: <n> is not an HTTP status code 状态码不在 100 到 999 之间。 使用真实存在的状态码。

当节点由面板描述时,obfs 和 obfs_password 来自面板,此时这些混淆相关的消息指向的是面板上的设置。哪些设置来自哪里,见 katana Hysteria 2。

节点的 [node.route] 与 etemenanki-app 的 [route] 使用同一套代码编译,因此打印的是路由规则与 geodata 中的消息。不同之处在于:

  • 规则只接受 outbound、domain_suffix、cidr、port、geosite 和 geoip。其他匹配条件(例如 domain_keyword)都是解析错误:unknown field `domain_keyword`, expected one of `outbound`, `domain_suffix`, `cidr`, `port`, `geosite`, `geoip`;
  • route references unknown outbound tag: <tag> 表示该 tag 既不是 [[outbound]] 的 tag,也不是内置的 direct、block、freedom 和 blackhole 之一。没有 default 时,未匹配的流量走 direct;
  • 启动时,消息跟在 node <id>: build router: 之后,katana 会跳过该节点。重载时的情况见 katana 重载失败。

rule_list_path 不会导致错误。如果无法读取该文件,节点会在没有它的情况下启动,并记录警告 cannot read rule_list_path <path>: <error>;不是合法正则表达式的行会被跳过,并记录 invalid local rule "<line>": <error>。见审计规则。

这些日志行来自 katana::runtime 和 katana::manager::node 日志 target。

日志行 发生了什么 应当怎么做
config reload failed, keeping current: <error> 新文件无法读取或解析失败。没有应用任何内容。 修正文件后重新保存。
reload: bad outbounds, keeping current config: <error> 新的 [[outbound]] 列表,或与之一同构建的 [dns] 表,构建失败。没有应用任何内容,节点的变更也不例外。katana 只在 [[outbound]] 也发生变化时才重建 [dns],因此单独修改 [dns] 既不会被检查,也不会被应用,直到重启为止。 修正出站或 [dns] 后重新保存。用 katana --test 检查 [dns]。
invalid log level "<value>": <error> 新的 [log].level 无法解析。旧的过滤规则继续生效,尽管同时也会记录 reload: log level → <value>。 改正日志级别。
reload: node <panel>@<host>#<id>[/<type>]: <error>; keeping current config 重载新增的节点,或 [[node]] 表发生变化的节点的面板客户端,构建失败,例如 unknown panel_type "<value>"、unknown node_type "<value>" 或 build router: <error>。没有应用任何内容:每个运行中的节点都保留原有配置。启动时构建失败的节点会在每次重载时重新构建,因此只要它仍有错误,每次重载都会被拒绝。<panel> 是小写的 panel_type,/<type> 是 katana 向 Xboard 或 V2board 面板请求的节点类型。 修正该节点后重新保存。保存前先运行 katana --test。
node <id>: config edit refused, keeping the running one: <error> 某个运行中节点的新 [node.route] 编译失败,例如 route references unknown outbound tag: <tag>。该节点没有应用此次修改中的任何内容,连接保持不断。重载的其余部分已经应用。 修正规则后重新保存。保存前先运行 katana --test。
node <id>: route rebuild failed, keeping current: <error> [[outbound]] 的变更破坏了某个节点的规则,例如删除了规则所引用的出站 tag。该节点保留原有规则,但 katana 仍会重建它的监听器,这会断开它的连接。 恢复该出站,或把规则改为指向其他 tag。
config watcher disabled (no live reload): <error> 启动时无法监视配置所在目录。katana 照常运行,但在重启之前会忽略对文件的修改。 检查该目录。

每种变更对运行中节点的影响,见 katana 热重载。