The contract/registry/warnings.json dictionary is shared with LxBox: both apps report the same event under the same name.
severity: error means the node was dropped; warning and info stay on a surviving node.
alias_shadowed·info— Duplicate field removed: {path}amnezia_container_choice·info— Profile holds {count} containers, took {chosen}anytls_min_idle_invalid·warning— Field removed: invalid min_idle_sessionawg3_core_unsupported·warning— AmneziaWG 3.x: core too oldawg3_field_invalid·warning— AmneziaWG 3.x: field {path} not appliedawg3_header_key_invalid·error— AmneziaWG 3.x: invalid header keyawg3_padding_too_short·error— AmneziaWG 3.x: {field} shorter than {min}awg3_random_trailers_wide_headers·info— AmneziaWG 3.x: wide headers with random trailersawg_header_invalid·warning— AmneziaWG: magic header {path} not appliedawg_headers_overlap·error— AmneziaWG: headers {a} and {b} overlapawg_mtu_clamped·warning— AmneziaWG: MTU lowered to 1280awg_mtu_high·info— AmneziaWG: MTU above 1280chain_cycle_through_direction·warning— Chain {chain} excluded from {direction}chain_hop_missing·error— Chain: hop {position} not foundchain_invalid·error— Chain is malformedchain_nested_position·error— Chain: nested chain at position {position}chain_strip_utls_on_reality·warning— Chain: uTLS kept because of REALITYchain_unsupported_by_core·error— Chains are unavailable in core {version}core_rejected·error— The core rejected this serverdetour_chain_too_deep·warning— Chain shortened to {limit} hopsdetour_cycle_broken·warning— Loop in the chain brokendetour_target_missing·warning— Chain cut: {target} not founddetour_to_group·warning— Chain cut: {target} is a groupdetour_with_listen_port·warning— {tag}: listening port removed for the hopdetour_with_tls_fragment·info— {tag}: TLS fragmentation removed for the hopdialer_proxy_unusable·error— Preceding proxy {target} is unusabledirection_filter_matched_nothing·warning— Direction {direction}: filter matched no nodesduplicates_collapsed·info— Repeats of this server in the subscription: {count}ech_ignored·info— ECH from the link removedfield_conflict·warning— Field {path} removed: conflicts with {with}field_missing·error— Required field {field} is missingfield_requires·warning— Field {path} removed: {requires} is missingfields_order_invalid·warning— {a} is greater than {b}flow_deprecated·info— Obsolete flow removedform_unrecognized·error— Entry could not be readgroup_empty·warning— Group {tag} left without membersgroup_member_dropped·warning— Group {tag}: {member} left the groupgroup_member_missing·warning— {count} group members not importedgrpc_multi_mode_ignored·warning— gRPC: multi mode not appliedhysteria2_server_ports_item_invalid·warning— Hysteria2: port hopping range droppedhysteria_server_ports_item_invalid·warning— Hysteria: port hopping range droppedjson_field_unknown·info— Configuration: field {query_name} not readmasque_tls_field_ignored·info— MASQUE: TLS field {path} not usedmasque_tls_fragment_h3·info— MASQUE over h3: {path} removedmasque_vhttp_invalid·warning— MASQUE: HTTP version {value} set to h3max_nodes_exceeded·warning— {skipped} nodes over the limit skippednaive_extra_headers_invalid·info— naive: header {entry} discardednaive_padding_ignored·info— naive: padding parameter ignorednaive_unavailable·error— naive is unavailable in this buildobfs_object_flattened·info— Obfuscation password taken from an objectobfs_password_missing·warning— Obfuscation removed: no passwordobfs_unknown·warning— Unknown obfuscation removedopenvpn_core_unsupported·warning— OpenVPN is unavailable in this corepacket_encoding_unknown·warning— Field removed: unknown packet_encodingpassword_empty·warning— Password is emptyport_invalid·error— Invalid port {value}protocol_unsupported·error— Protocol {scheme} is not supportedprovider_banner_link·info— Subscription: provider notice instead of a serverreality_fp_not_chrome·info— REALITY: fingerprint {value} may not connectreality_fp_random_pinned·info— REALITY: fingerprint random pinned to chromereality_key_share_invalid·info— REALITY: key_share removedreality_pbk_invalid·warning— REALITY disabled: invalid public keyreality_short_id_invalid·info— REALITY: short_id cleaned upreality_utls_enabled·info— REALITY: uTLS switched onreplace_group_empty·warning— Swap group {tag} is not builtreplace_tag_conflict·error— Swap group {tag}: the tag is already declaredscheme_unsupported·error— Link: scheme {scheme} is not supportedservice_record_ignored·info— Subscription: service record {scheme} skippedsource_detour_cycle·error— Node {tag} excluded: hops form a loopsource_detour_missing·error— Source chain broken: {target} not foundsource_detour_self·error— Node {tag} excluded: hop points at itselfss_method_invalid·error— Unsupported encryption method {method}ss_method_legacy·info— Shadowsocks: legacy cipherssh_user_default·info— SSH: user root substitutedtailscale_core_unsupported·warning— Tailscale is unavailable in this coretailscale_default_route_advertised·warning— Tailscale: default route {value} removed from advertised routestemplate_fragment_dropped·warning— Entry of {kind} from {owner} left outtemplate_int_clamped·warning— Value of {name} clampedtemplate_int_invalid·warning— Variable {name} is not a numbertemplate_rule_unconditional·warning— Rule from {owner} matches everythingtemplate_unknown_directive·warning— Unknown template directive {key}template_var_undeclared·warning— Variable {name} is not declaredtls_alpn_item_invalid·warning— TLS: bogus ALPN entry droppedtls_field_unsupported_naive·warning— naive: TLS field {path} removedtls_fragment_system_engine·warning— System TLS engine: {path} removedtls_insecure·info— Certificate verification disabledtls_not_applicable_quic·info— QUIC: TLS field {path} not applicabletransport_header_unsupported·error— TCP header obfuscation {value} is not supportedtransport_unsupported·warning— Transport replaced with {fallback}tuic_congestion_invalid·warning— Field removed: unknown congestion controltuic_udp_relay_mode_invalid·warning— Field removed: unknown UDP relay modetype_invalid·warning— Field {path} removed: wrong typeunknown_key·warning— Field removed: unknown keyuri_param_unknown·info— Link: parameter {query_name} not readuri_too_long·error— Link too long: {length} charactersutls_fp_unknown·warning— Unknown uTLS fingerprint replacedvision_with_transport·info— flow removed: incompatible with transportvless_encryption_invalid·error— VLESS encryption string is malformedvmess_security_unknown·warning— VMess: unknown cipher replaced with autowg_key_invalid·error— WireGuard: invalid keywgconf_dns_ignored·info— WireGuard: DNS from the configuration not appliedwgconf_extra_peer_dropped·warning— WireGuard: extra [Peer] sections droppedwgconf_param_unknown·info— WireGuard: unknown key {query_name}ws_early_data_converted·info— WebSocket: early data convertedxhttp_mode_forced_packet_up·warning— XHTTP mode set to packet-upxhttp_param_reset·warning— XHTTP: field {field} removedxray_cert_chain_pin_unsupported·warning— TLS: certificate pinning not appliedxray_domain_strategy_ignored·info— WireGuard: address family preference not appliedxray_extra_entries_dropped·warning— Configuration: extra entries droppedxray_reserved_base64_unsupported·warning— WireGuard: reserved bytes written as text not applied
severity: info · params: path, winner
Duplicate field removed: {path}
- What happened: The same setting arrived under several names; {winner} was kept and {path} removed. The core knows only one of these names, and a duplicate value has no effect.
- Why it happens: The same setting has several spellings across clients — insecure alone has eight of them, and the server name has sni and peer. A subscription assembled from different sources brings two of them at once, and the core knows only one.
- What you can do:
- Nothing to do: the setting took effect, only the duplicate name was removed.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: info · params: count, chosen
Profile holds {count} containers, took {chosen}
- What happened: The Amnezia profile holds {count} containers with different locations, and a single link yields one node. Container {chosen} was taken; import the profile as a subscription to get all of them.
- Why it happens: An Amnezia profile normally holds several containers — one per location — and a single link can only produce one node, so the default container was taken.
- What you can do:
- Nothing to do if this location is the one you need.
- To get all the locations at once, add the same profile as a subscription instead of a single link.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: value
Field removed: invalid min_idle_session
- What happened: The value {value} at {path} is not a non-negative integer. The field was removed, because the core rejects such a value and would refuse to start the whole config; the node works with the default.
- Why it happens: The field takes a non-negative whole number, and the entry holds something else — a typo in a hand-written body, or a panel that put a duration string like "30s" where a plain number belongs.
- What you can do:
- Nothing to do: the node works with the core's default.
- If you wrote the body yourself, put a non-negative whole number there.
Where it comes from:
anytlsmin_idle_session— the value does not fit the field → removed
severity: warning · params: reason
AmneziaWG 3.x: core too old
- What happened: The node uses AmneziaWG 3.x fields, which this core cannot read ({reason}). The node was excluded from the config, because the core rejects such a value and would refuse to start the whole config; the remaining nodes work.
- Why it happens: The node uses AmneziaWG 3.x fields, and reading them needs a core built with the with_awg tag, version 1.14.0-lx.32 or newer. An older or differently built core rejects the whole config as soon as a single such field appears in it.
- What you can do:
- Update the core to 1.14.0-lx.32 or newer, built with the with_awg tag.
- Use another node until the core is updated.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: path, value
AmneziaWG 3.x: field {path} not applied
- What happened: The AmneziaWG 3.x field {path} holds {value} — malformed, or a range whose bounds are reversed. The field was removed: the core rejects such a value and would refuse to start the whole config. The node stays and runs on the core defaults; if this field was part of what the server expects, the core falls back to plain WireGuard behaviour here and the handshake may not complete.
- Why it happens: The AmneziaWG 3.x fields are new and are usually copied by hand out of a .conf file, so a range ends up malformed or with its bounds swapped (a bigger number first). Reversed bounds are not silently corrected, because that is a typo you should see.
- What you can do:
- Check whether the node connects: if the server expects this field, it will not.
- If you wrote the range yourself, put the smaller bound first and re-import the configuration.
- Take the configuration from the provider again and re-import it.
Where it comes from:
wireguardcontent_padding_addition— the value does not fit the field → removeddisable_cookies— the value does not fit the field → removedib— the value does not fit the field → removedid— the value does not fit the field → removedip— the value does not fit the field → removedkeepalive_timeout— the value does not fit the field → removedmax_handshake_attempts— the value does not fit the field → removedrandom_trailers— the value does not fit the field → removedreject_after_time— the value does not fit the field → removedrekey_after_time— the value does not fit the field → removedrekey_timeout— the value does not fit the field → removeds3— the value does not fit the field → removeds4— the value does not fit the field → removed
severity: error
AmneziaWG 3.x: invalid header key
- What happened: The AmneziaWG 3.x header protection key is not a 32-byte key. The node was dropped, because the core rejects such a value and would refuse to start the whole config, and no handshake is possible without a correct key.
- Why it happens: The header protection key must be exactly 32 bytes in base64. A truncated copy-paste out of a .conf file, or a placeholder of all zeroes left in by a generator, gives exactly this.
- What you can do:
- Take the configuration from the provider again — the key is usually truncated when copied.
- Pick another node: without a correct key no handshake is possible.
Where it comes from:
wireguardheader_protection_key— the value does not fit the field → node dropped
severity: error · params: field, min
AmneziaWG 3.x: {field} shorter than {min}
- What happened: Header protection is enabled, but padding {field} is shorter than {min} bytes, from which the cipher nonce is taken. The node was dropped, because the core rejects such a pair and would refuse to start the whole config.
- Why it happens: Header protection and packet padding were set separately, and the padding stayed at its old small value or at zero — typical of a .conf assembled by hand, or of an older generator that added the key without touching the padding sizes.
- What you can do:
- Take the configuration from the provider again, already matched for header protection.
- Pick another node from this subscription.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: info
AmneziaWG 3.x: wide headers with random trailers
- What happened: The node combines random trailers with a very wide range of magic headers. Nothing was changed — this is a property of the settings themselves: a server of the reference implementation mistakes some outgoing packets for handshakes and drops them, which slows down upload.
- Why it happens: Both settings came from the server's configuration as its author wrote them: random trailers were turned on and the magic header ranges were left very wide. Nothing is malformed here — it is simply a combination that costs upload speed against reference-implementation servers.
- What you can do:
- Nothing to do: the node works, and this affects only upload speed.
- If upload is noticeably slow, ask the provider for a configuration with narrower header ranges.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: path, value
AmneziaWG: magic header {path} not applied
- What happened: The AmneziaWG magic header {path} holds {value}, which is neither a number nor a min-max range. The field was removed: the core rejects such a value and would refuse to start the whole config. The node stays, but this header is no longer sent — the core falls back to the plain WireGuard header, and if the server expects the AmneziaWG headers, the handshake may not complete.
- Why it happens: The AmneziaWG magic headers take a number or a min-max range. Junk here usually comes from a .conf file edited by hand, or from a generator that wrote an empty placeholder instead of the value.
- What you can do:
- Check whether the node connects: if the server expects the AmneziaWG headers, it will not.
- Take the configuration from the provider again and re-import it.
- If you edited the file yourself, write a number or a min-max range with the smaller bound first.
Where it comes from:
wireguardh1— the value does not fit the field → removedh2— the value does not fit the field → removedh3— the value does not fit the field → removedh4— the value does not fit the field → removedjc— the value does not fit the field → removedjmax— the value does not fit the field → removedjmin— set withoutjmax→ removedjmin— the value does not fit the field → removeds1— the value does not fit the field → removeds2— the value does not fit the field → removed
severity: error · params: a, b
AmneziaWG: headers {a} and {b} overlap
- What happened: The ranges of magic headers {a} and {b} overlap, so the core cannot tell the message types apart. The node was dropped, because the core rejects such an entry and would refuse to start the whole config.
- Why it happens: The magic header ranges were widened one at a time until they ran into each other — typical of a .conf tuned by hand. The core tells message types apart by these ranges, so overlapping ones leave it no way to do that.
- What you can do:
- Take the configuration from the provider again.
- If you edited the ranges yourself, make them non-overlapping and import the configuration again.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: value, path
AmneziaWG: MTU lowered to 1280
- What happened: The MTU at {path} was {value}, above the 1280 ceiling this launcher holds for AmneziaWG. The value was replaced with 1280, because AmneziaWG pads every packet and a higher MTU makes the tunnel connect and then carry no data.
- Why it happens: AmneziaWG wraps every packet in junk and padding, so an obfuscated packet is bigger than the plain WireGuard one the MTU was calculated for. Once it exceeds the path MTU the system refuses to send it at all ("sendmsg: message too long") instead of fragmenting it: the handshake completes, the tunnel looks up, and nothing goes through. Link generators copy the MTU from the plain WireGuard profile (1420) or from the Amnezia export (1376) without accounting for that overhead.
- What you can do:
- Nothing to do in most cases: 1280 is the MTU AmneziaWG itself recommends, and the tunnel works at it.
- If the node still carries no data, the MTU is not the cause — check the keys and the server.
Where it comes from:
wireguardmtu— the value is above1280when any ofjc,jmin,jmaxis set (and 25 more) → replaced with1280
severity: info · params: value, path
AmneziaWG: MTU above 1280
- What happened: The MTU at {path} is {value}, above the 1280 this launcher recommends for AmneziaWG. The value was kept as written, because the node was written by hand in the core's own form; be aware that a too-high MTU makes an AmneziaWG tunnel connect and then carry no data.
- Why it happens: AmneziaWG pads every packet, so the obfuscated packet is bigger than the plain WireGuard one the MTU was calculated for; past the path MTU the system refuses to send it ("sendmsg: message too long") instead of fragmenting. The value is kept here because this node was written by hand in the core's own form, and the launcher does not silently rewrite what you wrote yourself.
- What you can do:
- Nothing to do if the tunnel carries data: your server accepts this MTU.
- If the handshake succeeds but nothing goes through, lower the MTU to 1280 in the node body.
Where it comes from:
wireguardmtu— the value is above1280when any ofjc,jmin,jmaxis set (and 25 more), but the body came fromsingbox→ kept with a notice
severity: warning · params: chain, direction
Chain {chain} excluded from {direction}
- What happened: Direction {direction} did not take chain {chain} into its members, because that chain itself runs through this direction. Otherwise, choosing the chain inside the direction would loop the traffic back onto itself.
- Why it happens: The direction picks its members by a filter such as "all nodes", and the chain itself runs through this very direction. Taking the chain in would let you choose it inside the direction and loop the traffic back onto itself.
- What you can do:
- Nothing to do if the direction works as you meant it to.
- If the chain has to be in the direction, build it out of nodes rather than through this direction.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: error · params: position, target
Chain: hop {position} not found
- What happened: Position {position} of the chain points at {target}, which is not among the nodes and directions. The whole chain was excluded, because the core rejects a reference to a missing tag and would refuse to start the whole config.
- Why it happens: A position of the chain names a node or direction that is not there any more: the node disappeared from its subscription after an update, the direction was turned off, or the chain refers to something declared below it in the list — references forward are not allowed.
- What you can do:
- Open the chain and put an existing node or direction into that position.
- If the chain references something declared below it, move that entry above the chain.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: error · params: reason
Chain is malformed
- What happened: The chain breaks a rule of the core: {reason}. It was excluded, because the core rejects such an entry and would refuse to start the whole config.
- Why it happens: The chain breaks a rule of the core: fewer than two positions, an empty tag, a reference to itself, the same position twice, or an unknown key in the strip list. The form should have caught this before the chain was saved.
- What you can do:
- Open the chain and fix what the message names.
- A chain needs at least two different positions and a non-empty name.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: error · params: position, target
Chain: nested chain at position {position}
- What happened: The nested chain {target} stands at position {position}, while the core allows it only first. The chain was excluded, because the core rejects such an entry and would refuse to start the whole config.
- Why it happens: A nested chain was placed somewhere other than first. Every position after the first means "a node reached through the previous one", and a chain is not a node that can be rebuilt onto someone else's dialer.
- What you can do:
- Move the nested chain to the first position.
- Or replace it with the individual nodes it consists of.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: target
Chain: uTLS kept because of REALITY
- What happened: The chain is set to strip uTLS, but hop {target} runs REALITY, which cannot work without it. Stripping uTLS was turned off for this chain, so every hop keeps its fingerprint; the chain works.
- Why it happens: The chain was set up to strip uTLS from its inner hops, and a node in one of those positions runs REALITY. In REALITY the TLS fingerprint (the ClientHello) is a load-bearing part of the protocol, not camouflage, and the core applies the strip list to all hops at once, so it cannot spare just one.
- What you can do:
- Nothing to do if the chain works.
- To strip uTLS on the other hops, put a node without REALITY into that position.
Where it comes from:
chainstrip.tls.utls— a hop at position 2 or later requires this path → not stripped
severity: error · params: version, tag
Chains are unavailable in core {version}
- What happened: The chain {tag} cannot be built: core {version} does not know the chain type. The chain was excluded, because the core rejects an unknown type and would refuse to start the whole config.
- Why it happens: Chains are an extension of the lx fork: they need a core built with the with_lx_chain tag. A stock sing-box, or a fork build without that tag, does not know the chain type at all.
- What you can do:
- Update the core to a build of the lx fork that includes the with_lx_chain tag.
- Use a direction or a single node instead of the chain until then.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: error · params: reason
The core rejected this server
- What happened: The core rejected this server. Its technical message: {reason}. The server was turned off so the VPN could start. Turn it back on and the core will check it again.
- Why it happens: The core checks the whole configuration at once and refuses to start on the first server it cannot accept — otherwise one broken line would leave every server unusable. Something in this server is outside what the core accepts and outside what the app's own checks look at: a value from a newer or older core, a field the provider filled in by hand, or a combination nobody anticipated. The text above is the core's own, passed on unchanged.
- What you can do:
- Update the subscription: the provider may have already fixed this server.
- Turn the server back on after updating the subscription or the core — it will be checked again at the next start.
- If the server stays broken, remove it or pick another one.
- Tell the developers: a server reaching the core in this state is a gap in the app's own checks.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: limit
Chain shortened to {limit} hops
- What happened: The detour chain of this node was longer than the allowed {limit} hops. The tail was cut off, because a chain of unlimited depth is not passed to the core; the node keeps working.
- Why it happens: The imported config builds a chain deeper than the application passes to the core — usually a config assembled out of several subscriptions, where every node was routed through the previous one.
- What you can do:
- Nothing to do: the node works with the shortened chain.
- If you need the full depth, simplify the chain in the source config.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: target
Loop in the chain broken
- What happened: The detour chain of this node looped back on itself through {target}. The closing link was removed, because the core rejects such a config and would refuse to start it; the node keeps working with a shortened chain.
- Why it happens: An imported sing-box config described chains that close on themselves — the node goes through a hop that in turn goes back through this node. Hand-assembled configs and merged subscriptions collect such loops easily.
- What you can do:
- Nothing to do if the node works: it now connects with a shortened chain.
- If you need the full chain, fix the detour links in the source config.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: target
Chain cut: {target} not found
- What happened: The imported config sends this node through {target}, but there is no such node in it. The chain was cut, because the core rejects a reference to a missing tag and would refuse to start the whole config; the node connects directly.
- Why it happens: The imported config references a hop by tag, but the node with that tag did not make it into the import — it was dropped as unsupported, or the provider exports only part of their own config.
- What you can do:
- Nothing to do if the node works: it now connects directly.
- If the traffic has to go through that hop, ask the provider for a config with all the nodes it references.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: target
Chain cut: {target} is a group
- What happened: This node was routed through {target}, which is a group rather than a server. The chain was cut, because a group cannot be a hop and the core would refuse to start the whole config; the node connects directly.
- Why it happens: The imported config points a node's detour at a selector or urltest group. Other clients tolerate that spelling, but in sing-box a group is a choice between routes, not a hop in one.
- What you can do:
- Nothing to do if the node works: it now connects directly.
- If you need a chain, point the detour at a specific node instead of a group.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: tag, target
{tag}: listening port removed for the hop
- What happened: Node {tag} is routed through {target}, and a node that listens on its own port cannot go through a hop: the core rejects that combination and would refuse to start the whole config. The listening port was removed, the hop stays — the node connects through {target}.
- Why it happens: The node arrived with its own listening port (from a .conf file, a link or an imported config), and you assigned a hop to it — personally or through its folder. The core does not allow those two together.
- What you can do:
- Nothing to do if the node works through the hop.
- If the node has to listen on its port, remove the hop assigned to it.
Where it comes from:
wireguardlisten_port— conflicts withdetour→ removed
severity: info · params: tag, target
{tag}: TLS fragmentation removed for the hop
- What happened: Node {tag} is routed through {target}, so its TLS runs inside the hop's tunnel, where splitting the ClientHello does not help against DPI. An explicit fragmentation setting would also turn off the record fragmentation the core applies to such nodes on its own and add a 500 ms pause per segment. The setting was removed; the core's own default applies.
- Why it happens: The node arrived with TLS fragmentation (from a subscription or a link), and you assigned a hop to it — personally, through its folder or in a chain.
- What you can do:
- Nothing to do: fragmentation belongs on the hop that connects directly.
- If the hop itself needs fragmentation, turn it on for the hop node.
Where it comes from:
severity: error · params: target, cause
Preceding proxy {target} is unusable
- What happened: The node goes out through {target}, which cannot serve as a hop ({cause}). The node was dropped on purpose: without that hop its traffic would go directly, revealing the connection.
- Why it happens: The entry comes from an Xray config, where a node is routed through another one via dialerProxy. The hop it names is not there or cannot serve as one, and letting the node out directly would reveal the connection it was supposed to hide.
- What you can do:
- Ask the provider for a config that carries all the nodes its chains reference.
- Pick another node from this subscription.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: direction, filter, count
Direction {direction}: filter matched no nodes
- What happened: The node filter {filter} of direction {direction} matched none of the {count} nodes. The direction was left without nodes, so its traffic is blocked (the default member).
- Why it happens: The filter no longer matches the node names — typically the provider renamed its servers, or the filter was written for another subscription.
- What you can do:
- Check the node filter of the direction against the current node names.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: info · params: count, names
Repeats of this server in the subscription: {count}
- What happened: The subscription lists this same server again with identical settings, under the names: {names} (repeats: {count}). They are one and the same connection, so only this entry is kept.
- Why it happens: The provider repeats one server under several names — often different countries or brands. The address, keys and every other setting match exactly; only the label differs, so traffic through any of these entries takes the same path and leaves through the same exit.
- What you can do:
- Nothing to do: nothing was lost, the subscription simply has fewer distinct servers than entries.
- If you need the countries named in the list, ask the provider: these names lead to the same server.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: info · params: query_name
ECH from the link removed
- What happened: The link carried an Xray-style ECH parameter ({query_name}={value}): it holds another client's key, and the handshake with it would fail. The parameter was removed and the node connects without ECH. A tls.ech block from a sing-box configuration is not affected.
- Why it happens: The parameter comes from an Xray-style link: Xray passes an ECH key inside the link itself, while sing-box does not read it there. The key in it belongs to another client's configuration, so a handshake with it would fail anyway.
- What you can do:
- Nothing to do: the node connects without ECH, exactly as it would in any sing-box client.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: path, with
Field {path} removed: conflicts with {with}
- What happened: The fields {path} and {with} are mutually exclusive in the core. {path} was removed, because the core rejects such a pair and would refuse to start the whole config.
- Why it happens: Two settings that the core treats as mutually exclusive arrived together — usually from a subscription assembled out of different sources, or from a body where one option was added without removing the one it replaces.
- What you can do:
- Nothing to do if the node works: the lower-priority field was removed and the other one took effect.
- If you wrote the body yourself, leave only the setting you actually need.
Where it comes from:
dialertcp_fast_open— not supported byanytls→ removed
hysteria2realm— conflicts withserver_port→ removedrealm— conflicts withserver_ports→ removedrealm— conflicts withserver→ removedserver_ports— conflicts withrealm→ removed
tailscaleexit_node— conflicts withadvertise_exit_node→ removed
tlscertificate_public_key_sha256— conflicts withtls.certificate_path→ removedcertificate_public_key_sha256— conflicts withtls.certificate→ removeddisable_sni— conflicts withtls.reality.enabled→ removedech.enabled— conflicts withtls.reality.enabled→ removedreality.enabled— conflicts withtls.disable_sni→ removedreality.enabled— conflicts withtls.ech.enabled→ removedreality.enabled— conflicts withtls.spoof→ removedspoof— conflicts withtls.disable_sni→ removedspoof— conflicts withtls.reality.enabled→ removed
transportsxhttp.xmux.max_concurrency— conflicts withtransport.xmux.max_connections→ removed
tuicudp_relay_mode— conflicts withudp_over_stream→ removed
wireguard
severity: error · params: field
Required field {field} is missing
- What happened: The entry has no {field}, although the protocol requires it. The node was dropped, because the core rejects such an entry and would refuse to start the whole config.
- Why it happens: The entry was generated by a panel that lost a mandatory value, or the link was cut short when it was copied: a password, a UUID or an address simply is not there. Hand-written JSON bodies lose the same fields to a typo in a key name.
- What you can do:
- Copy the link again from the provider's page — a truncated link is the usual cause.
- Ask the provider to fix the entry in the subscription.
- If you typed the JSON body yourself, add the missing field.
Where it comes from:
anytlstls— required and missing → node dropped
chainoutbounds— required and missing → node dropped
dialerserver— the value does not fit the field → node dropped
hysteriatls— required and missing → node dropped
hysteria2obfs.password— required and missing → node droppedtls— required and missing → node dropped
masqueprivate_key— the value does not fit the field → node droppedpublic_key— the value does not fit the field → node dropped
naivetls— required and missing → node dropped
shadowsockspassword— required and missing → node dropped
trojanpassword— required and missing → node dropped
tuictls— required and missing → node dropped
vlessuuid— required and missing → node dropped
vmessuuid— required and missing → node dropped
wireguardpeers— required and missing → node droppedpeers.address— the value does not fit the field → node dropped
severity: warning · params: path, requires
Field {path} removed: {requires} is missing
- What happened: The field {path} only makes sense together with {requires}, which is absent or invalid. It was removed, because the value has no effect on its own.
- Why it happens: The setting only works in a pair, and its partner is missing or invalid — a REALITY short_id without a valid public key, for instance. Sloppy subscriptions and hand-written bodies lose the second half of such a pair easily.
- What you can do:
- Nothing to do if the node works: the field could not have done anything on its own.
- If you need this setting, add the field it depends on as well.
Where it comes from:
hysteria2obfs.max_packet_size— set withoutobfs.type→ removedobfs.min_packet_size— set withoutobfs.type→ removed
masqueprivate_key— set withoutpublic_key→ removedpublic_key— set withoutprivate_key→ removed
shadowsocksplugin_opts— set withoutplugin→ removed
tailscaleexit_node_allow_lan_access— set withoutexit_node→ removed
tlsclient_certificate— set withouttls.client_key→ removedclient_key— set withouttls.client_certificate→ removedreality.key_share— set withouttls.reality.public_key→ removedreality.short_id— set withouttls.reality.public_key→ removedspoof_method— set withouttls.spoof→ removed
transportsxhttp.session_length— set withouttransport.session_table→ removedxhttp.session_table— set withouttransport.session_length→ removed
wireguard
severity: warning · params: a, b, value, with
{a} is greater than {b}
- What happened: The node sets {a} = {value} above {b} = {with}, but the core requires {a} not to exceed {b} and would refuse to start the whole config with such a pair. Both fields were removed; the node works without them.
- Why it happens: The bounds were typed in the wrong order or swapped by hand. Which of the two numbers is wrong cannot be told from the node itself, so neither is kept.
- What you can do:
- Take the configuration from the provider again.
- If you set the values yourself, put the smaller bound first and import the configuration again.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: info · params: flow
Obsolete flow removed
- What happened: The entry carried flow={flow}, which current cores no longer accept. The field at {path} was removed, because the core rejects such a value and would refuse to start the whole config; the node keeps working.
- Why it happens: The value comes from an old Xray-era panel: xtls-rprx-direct, -origin and -splice were dropped from the protocol years ago, but outdated generators still write them into links. Broken subscriptions also put plain junk into this field.
- What you can do:
- Nothing to do: the node works, and the obsolete value would not have done anything anyway.
Where it comes from:
severity: error
Entry could not be read
- What happened: The entry is not a link or a configuration this app can read: it is not a link at all, or its encoded part (base64, a compressed profile) does not decode. The node was dropped; the rest of the subscription was read as usual.
- Why it happens: The link was cut short or damaged when it was copied, a panel produced a broken payload, or the line is not a node link at all — a stray word or a piece of HTML.
- What you can do:
- Copy the link again from the provider's page — a truncated link is the usual cause.
- Ask the provider to fix the entry in the subscription.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: tag
Group {tag} left without members
- What happened: None of the members of group {tag} could be resolved to a node. The group was dropped, because an empty group makes the core refuse to start the whole config; the nodes themselves are unaffected.
- Why it happens: The group lists its members by tag, and none of those tags gave a node: the entries were dropped during the import as unsupported or malformed, or the provider exported the group without the servers it points at.
- What you can do:
- Nothing to do if you use the nodes directly: they were not affected.
- If you need the group, ask the provider for a config that carries its servers too.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: tag, member
Group {tag}: {member} left the group
- What happened: Member {member} of group {tag} did not resolve to a node when the config was built: the node is gone, disabled, or was excluded from the config itself. The group was kept without it; the other members work as before.
- Why it happens: The group lists its members by reference, and this reference found no live node at build time: the node disappeared from its subscription after an update, was renamed or deleted, was turned off by you or by the application, or was itself dropped from the config because of a problem of its own.
- What you can do:
- Nothing to do if the group still has the servers you need.
- If you need this member, turn the node back on or fix the problem that excluded it; after a subscription update, check that the node still exists.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: count
{count} group members not imported
- What happened: Some members of this group ({count}) did not survive the import: their entries reference nodes that are not present. The group was kept without them.
- Why it happens: The group lists its members by tag, and some of those tags gave no node: the entries were dropped as unsupported or malformed during the import, or the provider exported the group without part of its servers.
- What you can do:
- Nothing to do if the group still has the servers you need.
- If servers are missing, ask the provider to fix the subscription and import it again.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning
gRPC: multi mode not applied
- What happened: The element asks for the gRPC multi mode. This build of the core has only the regular mode, and the node was imported with it. If the server accepts multi-mode clients only, this node will not connect.
- Why it happens: Xray can carry a gRPC stream two ways — one request per connection (gun) or several multiplexed inside one (multi). sing-box implements the first one only, and there is no field to ask for the second. Most servers accept both, so the node usually works; a server configured for multi alone will refuse it.
- What you can do:
- Check whether the node connects — if it does, nothing needs doing.
- If it does not, ask the provider for a node without multi mode, or pick another transport.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: path, value
Hysteria2: port hopping range dropped
- What happened: The port hopping list holds {value} at {path}, which is not a pair of port numbers from 0 to 65535. That single entry was dropped; the remaining ranges were kept and port hopping still works on them. Had it been kept, the core would have refused to load the whole configuration.
- Why it happens: The provider wrote the address and the ports as one string in the
mportparameter (mport=198.51.100.24:443,20000-30000), so the host name ended up inside the port list; or the panel wrote a port above 65535 or with leading zeros (99999:99999,00443:00444). - What you can do:
- Nothing to do: the node works, and port hopping uses the ranges that were written correctly.
- If the node does not connect, take the link from the provider again — their panel writes the port list in a form the core does not accept.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: path, value
Hysteria: port hopping range dropped
- What happened: The port hopping list holds {value} at {path}, which is not a pair of port numbers from 0 to 65535. That single entry was dropped; the remaining ranges were kept and port hopping still works on them. Had it been kept, the core would have refused to load the whole configuration.
- Why it happens: The provider wrote the address and the ports as one string in the
mportparameter (mport=198.51.100.24:443,20000-30000), so the host name ended up inside the port list; or the panel wrote a port above 65535 or with leading zeros (99999:99999,00443:00444). - What you can do:
- Nothing to do: the node works, and port hopping uses the ranges that were written correctly.
- If the node does not connect, take the link from the provider again — their panel writes the port list in a form the core does not accept.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: info · params: query_name
Configuration: field {query_name} not read
- What happened: The element carries the field {query_name}, which is not described for this protocol. The node works and the field changed nothing: it was not read at all. One code is raised per unread field.
- Why it happens: The field belongs to another client's dialect, to a newer version of the core, or it is a typo in a hand-written body. Service keys of the element itself (protocol, tag, remarks) and containers whose leaves the table reads (settings, streamSettings) are expected there and are not reported.
- What you can do:
- Nothing to do if the node works: the field had no effect here anyway.
- If you wrote the body yourself, check the spelling of the field.
- If the field belongs to a newer core, update the core.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: info · params: path
MASQUE: TLS field {path} not used
- What happened: MASQUE builds its TLS from the profile and the HTTP version (vhttp), and the core ignores the field {path} for this protocol. The field was removed; the node connects exactly as it would have anyway.
- Why it happens: The subscription or a hand-written config applies one TLS template to every protocol, so a MASQUE node was handed ALPN, ECH, REALITY or kTLS settings it cannot use.
- What you can do:
- Nothing to do: the node works, and the removed setting had no effect on MASQUE.
Where it comes from:
severity: info · params: path, with
MASQUE over h3: {path} removed
- What happened: With {with} set to h3 the MASQUE tunnel runs over QUIC, where TLS travels inside QUIC packets and there are no TLS records over TCP to split. The core ignores {path} there, so the field was removed; the node works as before.
- Why it happens: TLS fragmentation was set for a node that uses HTTP/3. It helps only on the HTTP/2 path (vhttp h2 or auto).
- What you can do:
- Nothing to do if the node connects.
- If you need fragmentation against DPI, set vhttp to h2 or auto for this node.
Where it comes from:
masquefragment— conflicts withvhttpwhenvhttpish3→ removedrecord_fragment— conflicts withvhttpwhenvhttpish3→ removed
tlsfragment— conflicts withvhttpwhenvhttpish3→ removedrecord_fragment— conflicts withvhttpwhenvhttpish3→ removed
severity: warning · params: value
MASQUE: HTTP version {value} set to h3
- What happened: The MASQUE HTTP version {value} at {path} is outside the values the core accepts. It was set to h3, because the core rejects such a value and would refuse to start the whole config.
- Why it happens: The core accepts only h3, h2 and auto here. Another value comes from a typo or from an obsolete spelling of the parameter that older generators still write.
- What you can do:
- Check that the node connects on h3 — that is what it was set to.
- If the server needs another HTTP version, set vhttp to h2 or auto yourself.
Where it comes from:
severity: warning · params: limit, skipped
{skipped} nodes over the limit skipped
- What happened: The subscription returned more than {limit} nodes; {skipped} of them were skipped. The limit protects the application from subscriptions that generate nodes for whole address ranges.
- Why it happens: Subscriptions that generate a node per address range routinely produce thousands of entries. The limit keeps such a list from flooding the application and the operating system's network stack.
- What you can do:
- Nothing to do in most cases: the nodes that were imported work.
- If you need specific servers, ask the provider for a narrower subscription link.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: info · params: entry
naive: header {entry} discarded
- What happened: A pair from the naive extra-headers list ({entry}) is not a valid header: the separator is missing or the characters are not allowed. That pair was discarded, the rest were kept; if the server expects the discarded header, the node may be refused access.
- Why it happens: The extra-headers list in the link is written by hand more often than generated, and a pair loses its colon, picks up a space in the header name, or carries a line break — usually when the link was assembled or copied between editors.
- What you can do:
- Nothing to do if the node connects: the remaining headers were kept.
- If the server refuses access, fix that header pair — it is often the one that opens the door.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: info · params: value
naive: padding parameter ignored
- What happened: The link carried the naive parameter padding={value}, which has no counterpart in the core. The value has no effect and was dropped; the node keeps working.
- Why it happens: The padding parameter belongs to the naive client's own link format; sing-box has nothing matching it, so a link copied from a naive setup carries a setting this core cannot act on.
- What you can do:
- Nothing to do: the node works, the parameter simply has no effect here.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: error
naive is unavailable in this build
- What happened: The node uses the naive protocol, which this build cannot run: the core is missing the library it needs. The node was excluded so the rest of the config still starts.
- Why it happens: The naive protocol is not built into the core itself: it needs the separate libcronet library next to the core binary, and this build does not have it. Releases of the fork before 1.14.0-lx.4 did not ship the library at all.
- What you can do:
- Update the application to a version that ships libcronet with the core.
- Use another node from this subscription while naive is unavailable.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: info · params: path
Obfuscation password taken from an object
- What happened: The obfuscation at {path} arrived as an object, while this protocol takes it as a plain password string. The password was taken from the object and used as the string; the node connects with obfuscation as intended.
- Why it happens: Hysteria v1 takes the obfuscation secret as a plain string, while Hysteria2 writes the same key as an object {type, password}. Providers that convert configs automatically sometimes put the Hysteria2 form into a v1 entry; the core would reject such an entry and refuse to start the whole config.
- What you can do:
- Nothing to do: the node works with the password from the object.
Where it comes from:
severity: warning · params: type
Obfuscation removed: no password
- What happened: Obfuscation of type {type} was set without a password. The whole obfuscation block was removed, because the core rejects such an entry and would refuse to start the whole config; the node connects without obfuscation.
- Why it happens: The entry names an obfuscation type but the password for it was lost: either the link was truncated when copied, or the panel writes the type without the matching password field.
- What you can do:
- Copy the link again from the provider's page — a truncated link is the usual cause.
- Ask the provider to fix the entry: if the server expects obfuscation, this node will not connect without the password.
Where it comes from:
hysteriaobfs— an object arrived without a usablepasswordmember → removed
hysteria2obfs.password— the field is present
severity: warning · params: value
Unknown obfuscation removed
- What happened: The obfuscation type {value} at {path} is not one the core knows. The whole obfuscation block was removed, because the core rejects such a value and would refuse to start the whole config; the node connects without obfuscation.
- Why it happens: The Hysteria2 entry names an obfuscation type outside the two the core knows (salamander and gecko) — a typo in the link, or a name taken from another client's dialect.
- What you can do:
- Check whether the node connects — if the server requires obfuscation, it will not.
- Ask the provider for a link with a valid obfuscation type.
Where it comes from:
severity: warning · params: reason
OpenVPN is unavailable in this core
- What happened: The node uses OpenVPN, which this core cannot run ({reason}). The node was excluded from the config, because the core rejects such a value and would refuse to start the whole config; the remaining nodes work.
- Why it happens: OpenVPN is an extension of the lx fork: it needs a core built with the with_openvpn tag, version 1.14.0-lx.10 or newer. A core without it rejects the whole config as soon as such a node appears in it.
- What you can do:
- Update the core to 1.14.0-lx.10 or newer, built with the with_openvpn tag.
- Use another node until the core is updated.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: value
Field removed: unknown packet_encoding
- What happened: The value {value} at {path} is not a packet encoding the core knows. The field was removed, because the core rejects such a value and would refuse to start the whole config; the node keeps working.
- Why it happens: The value is a spelling from another client: sing-box knows only xudp and packetaddr, while Xray-era panels write other words into the same field. A typo gives the same result.
- What you can do:
- Nothing to do in most cases: the node works with the core's default UDP handling.
- If UDP traffic misbehaves on this node, ask the provider for a link with a valid packet encoding.
Where it comes from:
vlesspacket_encoding— the value does not fit the field → removed
vmesspacket_encoding— the value does not fit the field → removed
severity: warning · params: path
Password is empty
- What happened: The link carries an empty password in {path}. The node is kept as it is, but the server will most likely refuse authentication and the connection will not come up.
- Why it happens: A panel that builds links from a template leaves the password slot empty when the subscription has expired or the account has no active key; copying a link by hand loses the part after the colon just as easily.
- What you can do:
- Check the link at your subscription provider and copy it again in full.
- If the provider issues the password separately, add it to the node by hand.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: error · params: value
Invalid port {value}
- What happened: The port {value} is not a number in the range 1-65535. The node was dropped, because the core rejects such a value and would refuse to start the whole config.
- Why it happens: The port in the entry is not a number or falls outside 1-65535: usually a truncated or mangled link, or a generator that put a placeholder where the port should be.
- What you can do:
- Copy the link again from the provider's page.
- Ask the provider to fix the entry in the subscription.
Where it comes from:
dialerserver_port— the value does not fit the field → node dropped
wireguardpeers.port— the value does not fit the field → node dropped
severity: error · params: scheme
Protocol {scheme} is not supported
- What happened: The entry uses protocol {scheme}, which the core does not support. The node was dropped, because the core rejects such a value and would refuse to start the whole config.
- Why it happens: The subscription mixes in a protocol from another client's world: a sing-box config or an Xray array can carry an outbound type this core does not implement at all. Public and aggregated subscriptions collect such entries from different panels.
- What you can do:
- Pick another node from this subscription — this one cannot work here.
- Ask the provider whether they have a link for the same server in a supported protocol.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: info · params: message
Subscription: provider notice instead of a server
- What happened: The subscription carries an entry that looks like a link but points nowhere — the panel writes its notice this way. The provider's message: {message}. The entry was skipped; every other entry of the subscription was imported as usual.
- Why it happens: When a subscription has expired, is disabled or has run out of traffic, panels do not send an empty body: Remnawave writes a valid
vless://to0.0.0.0:1and 3x-ui asocks://to127.0.0.1:1080, putting the explanation into the remark after#. On expiry such an entry may be the only one in the body. Addresses like these are not servers — they are a way to deliver text to the user through a list that has room only for links. - What you can do:
- Read the provider's message — usually it says the subscription has expired or the device limit is reached.
- Renew or re-activate the subscription in the provider's panel, then update the subscription in the app.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: info · params: value
REALITY: fingerprint {value} may not connect
- What happened: The node uses REALITY with uTLS fingerprint {value}, which was kept as is. Modern REALITY servers expect the hybrid key exchange carried only by the chrome, firefox and safari fingerprints; with another one the server silently redirects the connection to its cover site.
- Why it happens: The subscription explicitly picked a fingerprint such as ios, android, edge, 360 or qq for a REALITY node. Modern REALITY servers (Xray v26.9.8 and newer) expect the hybrid key exchange that only the chrome, firefox and safari fingerprints carry, so such a choice may not connect.
- What you can do:
- If the node connects, nothing to do: the fingerprint was kept exactly as the subscription asked.
- If it does not connect, change the fingerprint to chrome in the node's settings.
- For firefox and safari, keep the core at 1.14.1-lx.3 or newer — older cores reject them.
Where it comes from:
tlsutls.fingerprint— the value is anything exceptchrome,chrome_psk,chrome_psk_shuffle,chrome_padding_psk_shuffle,chrome_pq,chrome_pq_psk,firefox,safari,random→ kept with a notice
severity: info · params: path, value
REALITY: fingerprint random pinned to chrome
- What happened: The node uses REALITY with uTLS fingerprint random at {path}. It was replaced with chrome: random makes the core pick one fingerprint per start, and two of the five it picks from lack the hybrid key exchange modern REALITY servers expect.
- Why it happens: The subscription asked for the fingerprint random. The core resolves it once per start to chrome, firefox, edge, safari or ios; edge and ios carry no X25519MLKEM768 key share, so against Xray v26.9.8 and newer such a node would fail in roughly two starts out of five, and with key_share hybrid the core would refuse the handshake.
- What you can do:
- Nothing to do: chrome is one of the fingerprints random picks from, and it works with every REALITY server.
Where it comes from:
tlsutls.fingerprint— the value israndomwhentls.reality.enabledistrue→ replaced withchrome
severity: info · params: value
REALITY: key_share removed
- What happened: The REALITY key_share at {path} is outside the values the core accepts ({value}). The field was removed, because the core rejects such a value and would refuse to start the whole config; the node works with the key exchange its fingerprint implies.
- Why it happens: The core accepts only hybrid or classical here. Anything else is a typo in a hand-written body or in a link — the parameter is new and has no counterpart in other clients, so generators copy it by hand.
- What you can do:
- Nothing to do in most cases: the node works with the key exchange its fingerprint implies.
- If the subscription really needed a specific exchange, set key_share to hybrid or classical.
- The field only reaches the config on core 1.14.1-lx.4 or newer.
Where it comes from:
tlsreality.key_share— the value does not fit the field → removed
severity: warning · params: value
REALITY disabled: invalid public key
- What happened: The REALITY public key at {path} is not a valid key ({value}) — a common defect of public subscriptions. The whole REALITY block was removed and the node downgraded to plain TLS, because the core rejects such a value and would refuse to start the whole config.
- Why it happens: A classic defect of sloppy public subscriptions: the generator writes something like pbk=enabled, or copies the REALITY public key into a node that has no REALITY at all. A real key is 43 base64url characters.
- What you can do:
- Check whether the node connects: on a server that really runs REALITY, plain TLS will not get through.
- Ask the provider to fix the entry, and re-import the subscription afterwards.
- Pick another node from this subscription.
Where it comes from:
tlsreality.public_key— the value does not fit the field → removed
severity: info · params: value
REALITY: short_id cleaned up
- What happened: The REALITY short_id at {path} contained characters outside hex or was too long ({value}). It was cleaned up, and if nothing usable was left, removed altogether — an empty short_id is valid, while a malformed one makes the core refuse to start the whole config.
- Why it happens: The panel wrote a short_id that is not hexadecimal or is longer than the core allows — a typo, or a value pasted from a different field. An empty short_id is perfectly normal, a malformed one is not.
- What you can do:
- Check whether the node connects: if the server expects a specific short_id, it will not.
- Ask the provider for a link with the correct short_id.
Where it comes from:
tlsreality.short_id— the value does not fit the field → removedreality.short_id— the value had to be cleaned up (hex_only) → value cleaned up
severity: info · params: path, requires
REALITY: uTLS switched on
- What happened: The node uses REALITY ({path}), but {requires} was missing or off. uTLS was switched on with the default chrome fingerprint, because the core refuses REALITY without it and would not start the whole config.
- Why it happens: REALITY is built on top of uTLS: the core requires the uTLS block to be enabled on every REALITY node. Hand-written configs and some converters leave it out.
- What you can do:
- Nothing to do: the node connects with the chrome fingerprint.
Where it comes from:
tlsreality.enabled— set withouttls.utls.enabled→tls.utls.enabledfilled in withtrue
severity: warning · params: tag, mode
Swap group {tag} is not built
- What happened: The swap group {tag} ({mode}) was not built: the source has no enabled nodes. Rules and Directions aimed at it will not work.
- Why it happens: An empty selector or auto group makes the core refuse the whole config, so the group is left out. The source either has no nodes yet (the subscription was never updated or came back empty) or every node in it is turned off.
- What you can do:
- Update the subscription or add nodes to the folder.
- Turn on at least one node of the source.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: error · params: tag, other
Swap group {tag}: the tag is already declared
- What happened: The swap group {tag} was not built: that name is already declared by another owner ({other}: a Direction, another source's swap above in the list, or a template tag). The source was built unfolded, and the rest of the config was built without the group, because two outbounds with one tag make the core refuse the whole config.
- Why it happens: The tag of a swap is a declared root name, just like the tag of a Direction. Two declared names cannot share a tag; a node with the same name is not a conflict — it gets a suffix.
- What you can do:
- Open the source's Group tab and give the swap a tag nobody else uses.
- Or rename the Direction that carries this tag.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: error · params: scheme
Link: scheme {scheme} is not supported
- What happened: The composition line starts with the scheme {scheme}, which no protocol section of the registry describes. The record was dropped: there is nothing to read it with.
- Why it happens: The link belongs to another client's world, or it is a newer scheme than this application knows. Aggregated public subscriptions collect links from different panels, and a panel sometimes writes the protocol's full name where the short alias was expected.
- What you can do:
- Update the application: a newer version may know this scheme.
- Ask the provider for a link to the same server in a supported protocol.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: info · params: scheme
Subscription: service record {scheme} skipped
- What happened: The subscription body carries a record with the service scheme {scheme}, which is a routing command for a neighbouring client rather than a server. It was skipped; every other entry of the subscription was imported as usual.
- Why it happens: Panels hand one body to several clients at once and mix routing commands (
incy://routing/…,happ://routing/…) in with the links, and repeat them in theRouting:header. Such a record never claimed to be a node, and this application does not execute another client's routing rules. - What you can do:
- Nothing to do: the subscription is healthy and its nodes were imported.
- Set up routing rules in the application itself — the provider's command was not applied.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: error · params: tag
Node {tag} excluded: hops form a loop
- What happened: The hops assigned to node {tag} lead back to it. The node was excluded on purpose: the core rejects such a loop and would refuse to start the whole config, and breaking the loop silently would send traffic directly, past the boundary you set.
- Why it happens: Two or more nodes were assigned as hops of each other — personally or through their folders — so the chain of hops closes on itself.
- What you can do:
- Pick the hops so that they do not lead back to the node.
- Or remove the hop from one of the nodes in the loop.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: error · params: target, count
Source chain broken: {target} not found
- What happened: You routed this source through {target}, and that node is gone. All {count} of its nodes were excluded on purpose: without the assigned hop the traffic would go directly, past the boundary you set.
- Why it happens: You assigned a hop to this source yourself, and the node serving as that hop is gone: it disappeared from its subscription after an update, was renamed, or was deleted.
- What you can do:
- Assign an existing node as the hop for this source.
- Or remove the hop if the source no longer needs to go through one.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: error · params: tag
Node {tag} excluded: hop points at itself
- What happened: Node {tag} is routed through itself. It was excluded on purpose: a node cannot be its own hop, and dropping the hop silently would send the traffic directly, past the boundary you set.
- Why it happens: The hop assigned to the node — personally or through its folder — resolved to the node itself: for example, the folder's hop is one of the folder's own nodes.
- What you can do:
- Assign a different node as the hop.
- Or take this node out of the folder whose hop it is.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: error · params: method
Unsupported encryption method {method}
- What happened: The Shadowsocks entry uses encryption method {method}, which the core does not support. The node was dropped, because the core rejects such a value and would refuse to start the whole config.
- Why it happens: The Shadowsocks entry names a cipher outside the eighteen the core implements: a name from another client's dialect, a typo, or the wrong letter case — the core's list is case-sensitive, so AES-128-GCM is not the same as aes-128-gcm.
- What you can do:
- Pick another node — this one cannot work with that cipher.
- Ask the provider to fix the cipher name in the subscription.
Where it comes from:
shadowsocksmethod— the value does not fit the field → node dropped
severity: info
Shadowsocks: legacy cipher
- What happened: The node uses the Shadowsocks cipher {value} at {path}. The core accepts it, but it is a stream cipher without authentication, so the traffic is weakly protected. The node is kept as is.
- Why it happens: The server is an old Shadowsocks installation: these stream ciphers predate the authenticated ones and are still handed out by panels that were set up years ago and never reconfigured.
- What you can do:
- Nothing to do: the node works as is.
- If the provider offers a node with a modern cipher, prefer it — a stream cipher without authentication protects the traffic weakly.
Where it comes from:
shadowsocksmethod— the value isaes-128-ctr,aes-192-ctr,aes-256-ctr,aes-128-cfb,aes-192-cfb,aes-256-cfb,rc4-md5,chacha20-ietf,xchacha20→ kept with a notice
severity: info
SSH: user root substituted
- What happened: No SSH user was given. root was written into the node explicitly: the core connects as root when the user is empty anyway, so the connection is unchanged. Change the user if the server expects a different one.
- Why it happens: The SSH entry was written without a user — in an imported sing-box config the user key is simply absent, since the core fills in root silently and the author saw no need to spell it out.
- What you can do:
- Nothing to do if the server really accepts root.
- If it expects a different user, set it in the node's settings.
Where it comes from:
severity: warning · params: reason
Tailscale is unavailable in this core
- What happened: The node uses Tailscale, which this core cannot run ({reason}). The node was excluded from the config, because the core rejects such a value and would refuse to start the whole config; the remaining nodes work.
- Why it happens: Tailscale is an extension of the lx fork: it needs a core built with the with_tailscale tag. A core without the tag rejects the whole config as soon as such a node appears in it.
- What you can do:
- Update the core to an lx fork build that includes the with_tailscale tag.
- Use another node until the core is updated.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: path, value
Tailscale: default route {value} removed from advertised routes
- What happened: The node advertises the default route {value} at {path}. The core refuses to start with it: offering this node as an exit to the internet is a separate setting, advertise_exit_node. The route was removed; the other advertised routes stay.
- Why it happens: A default route was written into the list of subnets to share, meaning "use this node as an exit". Tailscale expresses that with its own flag and rejects the route form.
- What you can do:
- To offer this node as an exit, turn on advertise_exit_node (the exit node checkbox of the Tailscale form).
- Otherwise nothing to do: the remaining routes are advertised.
Where it comes from:
tailscaleadvertise_routes— a list item is0.0.0.0/0,::/0→ item removed
severity: warning · params: owner, kind, reason
Entry of {kind} from {owner} left out
- What happened: After variable substitution an entry of {kind} from {owner} has no {reason}, which the core requires, so it was left out of the config. The rest of {owner} is kept.
- Why it happens: A variable the entry refers to has no value — a setting left empty or switched off by another setting — and the key with it was dropped. Without that key the entry is incomplete: a rule without a target, a DNS server without an address, a rule set without a source. Or a rule set the rule refers to is not in the config — its file is not downloaded yet — and without it the rule would apply to all traffic or all DNS queries.
- What you can do:
- Fill in the setting of {owner} the entry depends on.
- If a rule set of the rule is not downloaded yet, download it and rebuild the config.
- If the entry is not needed, nothing has to be done: the config works without it.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: name, value
Value of {name} clamped
- What happened: The value {value} of variable {name} is outside the range 0-65535 the core allows. It was clamped to the nearest bound, because the core rejects such a value and would refuse to start the whole config.
- Why it happens: The value was entered by hand and went past the range the core allows for this kind of number: port and similar fields fit in 0-65535, and a bigger number simply has nowhere to go.
- What you can do:
- Check the value of the variable: it was clamped to the nearest bound, which may not be what you meant.
- Enter a number in the range 0-65535.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: name, value
Variable {name} is not a number
- What happened: Variable {name} is declared numeric, but holds {value}. The value went into the config as is, so that the typo stays visible instead of being masked by a zero.
- Why it happens: The variable is declared as a number, but text was entered into it — a typo, a stray space, or a value pasted into the wrong field.
- What you can do:
- Enter a number into the variable, or change its declared type in the template.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: owner, kind
Rule from {owner} matches everything
- What happened: An entry of {kind} from {owner} has no match conditions, so it applies to all traffic or all DNS queries. It is included in the config as written.
- Why it happens: The rule is written without conditions, or its conditions are inside #if branches that are all off with the current settings. No variable is missing: this is how the template is written, not a failure.
- What you can do:
- If the rule should apply to everything (a bare sniff, a test rule), nothing has to be done.
- Otherwise add a condition to the rule in {owner} or turn on the setting that adds one.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: key
Unknown template directive {key}
- What happened: The template contains directive {key}, which this version does not know, or a malformed condition. The block was not included in the config: an unrecognized directive is not guessed at.
- Why it happens: The template uses a directive this version does not know — it was written for a newer application — or a condition is written incorrectly: an #if without a branch, or with both #and and #or at once.
- What you can do:
- Update the application if the template was made for a newer version.
- Check the condition in the template: an #if takes either #and or #or, not both.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: name
Variable {name} is not declared
- What happened: The template refers to variable {name}, which is not declared in its list of variables — most often a typo. The placeholder was left in the output as is, and a condition on it counts as false.
- Why it happens: The template refers to a variable name that its own list of variables does not declare — almost always a typo in the name, or a variable that was renamed in the list but not in the body.
- What you can do:
- Check the spelling of the name against the template's list of variables.
- Add the variable to the list if it is really needed.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: path, value
TLS: bogus ALPN entry dropped
- What happened: The ALPN list holds {value} at {path}, which is not a protocol identifier. That single entry was dropped; the remaining ones were kept. Offered as is, it would have made the server abort the handshake, because no such protocol exists.
- Why it happens: The source wrote several protocols as one value and nothing split them, so a comma or a space stayed inside a single entry.
- What you can do:
- Nothing to do: the node works with the protocols that were written correctly.
- If the node stops negotiating TLS, remove the ALPN setting from the entry — the core then offers the protocol the transport implies.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: path
naive: TLS field {path} removed
- What happened: The naive protocol reads only a few TLS settings, and {path} is not among them. The field was removed, because the core rejects such a value and would refuse to start the whole config.
- Why it happens: A naive node was given a full set of TLS settings — most often because the subscription applies one TLS template to every protocol. naive reads only a few of them, and the rest either stop the core from starting or are ignored.
- What you can do:
- Nothing to do: the node works, and the removed settings would not have applied to naive.
- If the node does not connect, ask the provider for a link without the extra TLS settings.
Where it comes from:
tlsalpn— not supported bynaive,masque→ removedcertificate_public_key_sha256— not supported bynaive→ removedcipher_suites— not supported bynaive→ removedclient_certificate— not supported bynaive→ removedclient_certificate_path— not supported bynaive→ removedclient_key— not supported bynaive→ removedclient_key_path— not supported bynaive→ removedcurve_preferences— not supported bynaive→ removeddisable_sni— not supported bynaive→ removedengine— not supported bynaive→ removedfragment— not supported bynaive→ removedfragment_fallback_delay— not supported bynaive→ removedhandshake_timeout— not supported bynaive→ removedinsecure— not supported bynaive→ removedkernel_rx— not supported bynaive,masque→ removedkernel_tx— not supported bynaive,masque→ removedmax_version— not supported bynaive→ removedmin_version— not supported bynaive→ removedreality— not supported bynaive,hysteria,hysteria2,tuic,masque→ removedreality.enabled— not supported bynaive→ removedrecord_fragment— not supported bynaive→ removedspoof— not supported bynaive→ removedspoof_method— not supported bynaive→ removedutls— not supported bynaive,hysteria,hysteria2,tuic,masque→ removedutls.enabled— not supported bynaive→ removed
severity: warning · params: path, with
System TLS engine: {path} removed
- What happened: The node uses the system TLS engine ({with}), which cannot split the ClientHello. The core would refuse to start the whole config with this combination, so {path} was removed; the engine stays and the node works without fragmentation.
- Why it happens: TLS fragmentation and the apple or windows TLS engine were both set for the node, usually in an imported sing-box config or by hand.
- What you can do:
- Nothing to do if the node connects.
- If you need fragmentation against DPI, remove the engine setting so the node uses the default Go TLS.
Where it comes from:
tlsfragment— conflicts withtls.enginewhentls.engineis one ofapple,windows→ removedrecord_fragment— conflicts withtls.enginewhentls.engineis one ofapple,windows→ removed
severity: info · params: path, value
Certificate verification disabled
- What happened: The entry sets {path} to {value}, so the server certificate is not verified. The value was kept as the provider sent it; connections to this node can be intercepted without being noticed.
- Why it happens: The provider deliberately turned certificate checking off — usually because the server runs a self-signed certificate — and wrote allowInsecure or insecure into the link. Sometimes it is a leftover from a test setup that was never cleaned up.
- What you can do:
- Nothing to do if you trust this provider: the node works as they intended it to.
- If you did not expect this, ask the provider why certificate verification is off on their server.
Where it comes from:
severity: info · params: path
QUIC: TLS field {path} not applicable
- What happened: This protocol runs over QUIC, where the core cannot use a uTLS fingerprint or REALITY at all. The field {path} was removed; the node connects exactly as it would have anyway.
- Why it happens: The subscription applies one TLS template to every protocol, so a QUIC node (hysteria, hysteria2, tuic, masque) was handed a fingerprint or REALITY keys. QUIC carries TLS 1.3 inside itself and the core builds it through the standard engine, which neither uTLS nor REALITY can provide — with such a block the outbound would not start at all.
- What you can do:
- Nothing to do: the node works, and the removed settings have no meaning over QUIC.
- If you need a fingerprint or REALITY, take a node on a TCP protocol — vless, trojan, vmess or anytls.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: error · params: value
TCP header obfuscation {value} is not supported
- What happened: The entry asks for Xray header obfuscation {value} over plain TCP. The core has no counterpart for it, so the node was dropped: it could only have been built as a node without obfuscation, and the server expects an HTTP header in the very first packet and would break the connection.
- Why it happens: Xray disguises a plain TCP stream as HTTP: the first packet carries a fabricated HTTP request, and the transport stays TCP. This is not the HTTP/2 transport of sing-box, which is a different protocol on the wire, so the value cannot be carried over to it. Panels write this obfuscation for nodes meant to pass DPI.
- What you can do:
- Pick another node from this subscription — this one cannot work here.
- Ask the provider for a link to the same server with a real transport (ws, grpc, httpupgrade, xhttp) instead of TCP header obfuscation.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: transport, fallback
Transport replaced with {fallback}
- What happened: The subscription asked for the {transport} transport, which this build of the core cannot run. The node was switched to {fallback}, because the core rejects an unknown transport and refuses to start the whole config.
- Why it happens: The subscription asked for a transport that this build of the core was not compiled with, or a transport that only another client understands — the Xray converter meets kcp/quic-style values that sing-box has no counterpart for, and XHTTP needs a build with the XHTTP transport included.
- What you can do:
- Check that the node works after the replacement — if it does not connect, pick another node.
- Ask the subscription provider for a link in a format sing-box supports.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: value
Field removed: unknown congestion control
- What happened: The TUIC congestion control {value} at {path} is not one the core knows. The field was removed, because the core rejects such a value and would refuse to start the whole config; the node works with the default algorithm.
- Why it happens: The core knows only cubic, new_reno and bbr here. Another word means a typo in the link or a name borrowed from another client, where the same algorithms are spelled differently.
- What you can do:
- Nothing to do in most cases: the node works with the core's default algorithm.
- If the speed on this node is poor, ask the provider for a link with a valid algorithm name.
Where it comes from:
tuiccongestion_control— the value does not fit the field → removed
severity: warning · params: value
Field removed: unknown UDP relay mode
- What happened: The TUIC UDP relay mode {value} at {path} is not one the core knows. The field was removed, because the core rejects such a value and would refuse to start the whole config; the node works with the default mode.
- Why it happens: The core knows only native and quic here. Another value is a typo in the link or a spelling from a panel that generates TUIC entries for a different client.
- What you can do:
- Nothing to do in most cases: the node works in the default mode.
- If UDP on this node misbehaves, ask the provider for a link with a valid relay mode.
Where it comes from:
tuicudp_relay_mode— the value does not fit the field → removed
severity: warning · params: path, value
Field {path} removed: wrong type
- What happened: The value {value} at {path} does not fit the type of that field and could not be converted. The field was removed, because the core rejects such a value and would refuse to start the whole config.
- Why it happens: The value is of the wrong kind for this field and could not even be converted: text where a number belongs, an object where a string belongs. Usually a typo in a hand-written body, or a panel that exports every value as a string.
- What you can do:
- Nothing to do if the node works: it runs with the core's default for that field.
- If you wrote the body yourself, put a value of the right kind there.
- Otherwise ask the provider to fix the entry in the subscription.
Where it comes from:
dialerinet4_bind_address— the value does not fit the field → removednetwork— the value does not fit the field → removed
hysteriaauth— the value does not fit the field → removedconnection_receive_window— the value does not fit the field → removeddown_mbps— the value does not fit the field → removedinitial_packet_size— the value does not fit the field → removedmax_concurrent_streams— the value does not fit the field → removedstream_receive_window— the value does not fit the field → removedup_mbps— the value does not fit the field → removed
hysteria2bbr_profile— the value does not fit the field → removedconnection_receive_window— the value does not fit the field → removeddown_mbps— the value does not fit the field → removedinitial_packet_size— the value does not fit the field → removedmax_concurrent_streams— the value does not fit the field → removedobfs.max_packet_size— the value does not fit the field → removedobfs.min_packet_size— the value does not fit the field → removedstream_receive_window— the value does not fit the field → removedup_mbps— the value does not fit the field → removed
masquemultiplexbrutal.down_mbps— the value does not fit the field → removedbrutal.up_mbps— the value does not fit the field → removedmax_connections— the value does not fit the field → removedmax_streams— the value does not fit the field → removedmin_streams— the value does not fit the field → removedprotocol— the value does not fit the field → removed
naiveinsecure_concurrency— the value does not fit the field → removedquic_congestion_control— the value does not fit the field → removedquic_session_receive_window— the value does not fit the field → removedstream_receive_window— the value does not fit the field → removedudp_over_tcp.version— the value does not fit the field → removed
shadowsocksudp_over_tcp.version— the value does not fit the field → removed
socksudp_over_tcp.version— the value does not fit the field → removedversion— the value does not fit the field → removed
tailscaleadvertise_routes— the value does not fit the field → removedlisten_port— the value does not fit the field → removedrelay_server_port— the value does not fit the field → removedsystem_interface_mtu— the value does not fit the field → removed
tlscertificate_public_key_sha256— the value does not fit the field → removedcurve_preferences— the value does not fit the field → removedengine— the value does not fit the field → removedmax_version— the value does not fit the field → removedmin_version— the value does not fit the field → removedserver_name— the value does not fit the field → removedspoof— the value does not fit the field → removedspoof_method— the value does not fit the field → removed
transportsws.max_early_data— the value does not fit the field → removed
tuicconnection_receive_window— the value does not fit the field → removedinitial_packet_size— the value does not fit the field → removedmax_concurrent_streams— the value does not fit the field → removedstream_receive_window— the value does not fit the field → removeduuid— the value does not fit the field → removed
vmessalter_id— the value does not fit the field → removed
wireguardaddress— the value does not fit the field → removedlisten_port— the value does not fit the field → removedmtu— the value does not fit the field → removedpeers.allowed_ips— the value does not fit the field → removedpeers.reserved— the value does not fit the field → removedudp_nat_max— the value does not fit the field → removedworkers— the value does not fit the field → removed
severity: warning · params: path
Field removed: unknown key
- What happened: The key {path} is not described for this protocol. It was removed, because the key is unknown to this version of the core and the core would refuse to start the whole config.
- Why it happens: The key is not part of this protocol in this version of the core: it may come from another client's dialect, from a newer core, or be a typo in a hand-written JSON body. The core refuses to start the whole config over one unknown key.
- What you can do:
- Nothing to do if the node works: the key had no effect here anyway.
- If you wrote the body yourself, check the spelling of the key or remove it.
- If the key belongs to a newer core, update the core.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: info · params: query_name
Link: parameter {query_name} not read
- What happened: The link carries the parameter {query_name}, which is not described for this protocol. The node works and the parameter changed nothing: it was not read at all. One code is raised per unread parameter.
- Why it happens: The parameter belongs to another client's dialect, to a newer version of the protocol, or it is a typo in a hand-edited link. Sharing links have no common registry of parameters, so every client writes what it knows; a parameter this protocol does not describe has nowhere to go in the node body.
- What you can do:
- Nothing to do if the node works: the parameter had no effect here anyway.
- If you edited the link yourself, check the spelling of the parameter.
- If the parameter belongs to a newer core, update the core.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: error · params: length, limit
Link too long: {length} characters
- What happened: The link is {length} characters long, above the limit of {limit}. It was not parsed: a link of unbounded length is not accepted from a subscription.
- Why it happens: A link this long is not a normal node link: usually several links glued into one line, a page of HTML that came through instead of a subscription body, or a generator that ran away.
- What you can do:
- Check that each link sits on its own line in the subscription body.
- Ask the provider for a correct subscription link.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: value
Unknown uTLS fingerprint replaced
- What happened: The uTLS fingerprint {value} at {path} is not in the core dictionary. It was replaced with a known one, because the core rejects such a value and would refuse to start the whole config.
- Why it happens: The link carries a fingerprint name from another client's dialect — v2rayN and Xray panels write things like HelloChrome_120 — or simply a misspelled word. The core keeps a closed list of names and rejects anything outside it.
- What you can do:
- Nothing to do in most cases: the node connects with the substituted fingerprint.
- If the node does not connect, ask the provider for a link with a fingerprint sing-box knows.
Where it comes from:
tlsutls.fingerprint— the value does not fit the field → replaced withchrome
severity: info · params: path, with
flow removed: incompatible with transport
- What happened: Without a VLESS Encryption layer, xtls-rprx-vision works only over bare TLS, but the node has {with} set and no encryption. The flow field at {path} was removed, because the value has no effect here; the node keeps working.
- Why it happens: The panel put flow=xtls-rprx-vision into every link it generates, without looking at whether the node uses a transport. Without an encryption layer Vision only exists over bare TLS, so on a WebSocket, gRPC or HTTP node it is simply left over.
- What you can do:
- Nothing to do: the node works, and the removed value had no effect on this transport.
Where it comes from:
severity: error · params: path, value
VLESS encryption string is malformed
- What happened: The encryption string {value} at {path} does not look like a value the core accepts: it must start with the method name and carry at least three more non-empty parts separated by dots. The node was dropped, because the core would refuse to start the whole config over such a string.
- Why it happens: The post-quantum layer is written as method.appearance.rtt, optionally followed by padding blocks, and ends with a key — all separated by dots. A string this short, this broken or starting with another method name is a truncated copy-paste, a line wrapped by a mail client or a chat, or a placeholder a panel wrote instead of a real value. Only the shape is checked here, never the grammar: a copy of the core's grammar would drift on the next core bump and start rejecting working nodes, so anything subtler is caught by the core itself.
- What you can do:
- Update the subscription: the provider may have already fixed the string.
- Take the encryption string from the provider again, in one piece and without line breaks.
- If this server has no post-quantum layer at all, remove the encryption parameter instead of shortening it.
Where it comes from:
vlessencryption— the value does not fit the field → node dropped
severity: warning · params: path, value
VMess: unknown cipher replaced with auto
- What happened: The VMess cipher {value} at {path} is not one the core knows. It was replaced with auto, because the core rejects such a value and would refuse to start the whole config. The node works, but on the cipher the server picks, not the one the subscription asked for.
- Why it happens: The core knows only auto, none, zero, aes-128-cfb, aes-128-gcm and chacha20-poly1305 here. Another word means a typo in the link, a cipher retired from the core (aes-128-ctr), or a name borrowed from another client, where the same ciphers are spelled differently.
- What you can do:
- Nothing to do in most cases: with auto the server picks the cipher itself and the node connects.
- If the node does not connect, ask the provider for a link with a cipher sing-box knows.
Where it comes from:
severity: error · params: path
WireGuard: invalid key
- What happened: The WireGuard key at {path} is not a 32-byte key. The node was dropped, because the core rejects such a value and would refuse to start the whole config, and no handshake is possible without a correct key.
- Why it happens: A WireGuard key is exactly 32 bytes in base64. A truncated copy-paste, a placeholder the panel shows instead of the key (a row of asterisks), or a word like enabled left in by a broken generator all give exactly this.
- What you can do:
- Take the configuration from the provider again: the key is usually truncated or masked when copied out of a web panel.
- Pick another node: without a correct key no handshake is possible.
Where it comes from:
wireguardpeers.pre_shared_key— the value does not fit the field → node droppedpeers.public_key— the value does not fit the field → node droppedprivate_key— the value does not fit the field → node dropped
severity: info · params: value
WireGuard: DNS from the configuration not applied
- What happened: The configuration asked for DNS {value} in its [Interface] section. The node works, but this address is not applied: a sing-box WireGuard endpoint has no DNS field of its own, and the launcher resolves names through its own DNS settings.
- Why it happens: DNS in a .conf file is an instruction to wg-quick, which rewrites the system resolver while the tunnel is up. sing-box does not work that way: it routes and resolves names itself, so the key has nowhere to go in the node body. Providers write it into every configuration they hand out, so its presence says nothing about the node being broken.
- What you can do:
- Nothing to do if names resolve: the launcher's own DNS settings are already in charge.
- If you need exactly this server, add it in the launcher's DNS settings instead of the node.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: count
WireGuard: extra [Peer] sections dropped
- What happened: The configuration holds {count} [Peer] sections. Only the first one became a node, because one node here is one peer; the rest were dropped, and any traffic those peers were meant to carry will not go through this node.
- Why it happens: wg-quick lets one interface hold several peers and splits traffic between them by AllowedIPs. A node in the launcher is a single server, so there is no place to put the second peer. Such a file usually comes from a site-to-site setup, or from a provider that packed several locations into one configuration.
- What you can do:
- Check that the first peer is the one you need: it is the one that became the node.
- If you need the others, import each peer as its own configuration, with the same [Interface] and one [Peer] each.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: info · params: query_name
WireGuard: unknown key {query_name}
- What happened: The configuration holds the key {query_name}, which is not described for a WireGuard node. The node works and the key changed nothing: it was not read at all.
- Why it happens: The key belongs to another client's dialect, to a newer version of AmneziaWG, or it is a typo in a hand-edited file. Keys that manage the interface itself rather than describe the node (PostUp, Table, SaveConfig and the like) are expected in a .conf and are not reported.
- What you can do:
- Nothing to do if the node works: the key had no effect here anyway.
- If you edited the file yourself, check the spelling of the key.
- If the key belongs to a newer AmneziaWG, update the core.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: info · params: max_early_data
WebSocket: early data converted
- What happened: The WebSocket path carried the Xray tail with early data, which the core describes as separate fields. It was converted to a limit of {max_early_data} bytes and a header name; without the conversion the server would answer 404.
- Why it happens: Xray hides the WebSocket early-data setting inside the path as a ?ed=N tail, while sing-box expects it as separate fields. A link copied from an Xray panel carries that tail, and left as is the server would treat it as part of the path.
- What you can do:
- Nothing to do: the node works, the setting was simply written the way sing-box expects it.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning
XHTTP mode set to packet-up
- What happened: The node asked for uplink_data_placement=header without naming an XHTTP mode, and that placement only makes sense in packet-up. The mode was set to packet-up, because the core rejects the pair without it and would refuse to start the whole config.
- Why it happens: The link set uplink_data_placement=header but never named an XHTTP mode — a common omission of panel generators, since that placement only makes sense in packet-up and the panel assumed it went without saying.
- What you can do:
- Check that the node connects — the change alters how it talks to the server.
- If it does not connect, ask the provider for a link that names the XHTTP mode explicitly.
Where it comes from:
transportsxhttp.mode— the field is absent → filled in withpacket-up
severity: warning · params: field, value
XHTTP: field {field} removed
- What happened: The XHTTP field {field} ({value}) is not allowed in this node's current mode. The field was removed and the mode left untouched, because the core rejects such a pair and would refuse to start the whole config.
- Why it happens: The link came from a generator that copies XHTTP parameters blindly: uplink_data_placement=header is only valid in packet-up mode, and the entry names a different mode. Such a pair is fatal for the whole config, not just for this node.
- What you can do:
- Nothing to do: the node works in the mode the entry asked for, without the invalid parameter.
- If the node does not connect, ask the provider to fix the XHTTP settings in the subscription.
Where it comes from:
transportsxhttp.mode— the value does not fit the field → removedxhttp.seq_placement— the value does not fit the field → removedxhttp.session_placement— the value does not fit the field → removedxhttp.uplink_data_placement— set withouttransport.modewhentransport.uplink_data_placementis one ofheader,cookie→ removedxhttp.uplink_data_placement— the value does not fit the field → removedxhttp.x_padding_method— the value does not fit the field → removedxhttp.x_padding_placement— the value does not fit the field → removed
severity: warning · params: value
TLS: certificate pinning not applied
- What happened: The element pins the server certificate chain by its hash. The node works and the certificate is still verified the usual way, but this extra check is not applied: the core pins a different thing — the hash of the server's public key, not of the certificate chain — and the two values never match.
- Why it happens: Both clients can pin the server certificate, but they hash different things: Xray hashes the raw certificates of the chain, sing-box hashes the public key taken from the leaf certificate. Carrying the value across would not add protection — it would break every handshake, which is the opposite of what pinning is for, so the value is deliberately not carried.
- What you can do:
- Nothing to do if the node connects: the certificate is still verified against the usual trust store.
- If you need pinning exactly, ask the provider for the hash of the server public key — that is the form this application can apply.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: info · params: value
WireGuard: address family preference not applied
- What happened: The element asked for the {value} address strategy. The node works, but the preference is not applied: the launcher writes the DNS server for a node as a plain tag, and a strategy without a server is dropped by the core. Names may resolve to IPv6 where the provider expected IPv4.
- Why it happens: Xray carries the address-family preference on the outbound itself. In sing-box the same setting lives inside the node's DNS resolver object, next to the name of the server that does the resolving — and the element never names such a server. Writing the strategy alone would either change the shape of that field for every scheme at once or invent a server tag the element did not ask for.
- What you can do:
- Nothing to do if the node connects: the preference only affects which address is tried first.
- If the node needs IPv4 only, set the address strategy in the launcher's DNS settings.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: query_name, count
Configuration: extra entries dropped
- What happened: The element holds {count} entries in {query_name}. Only the first one became a node: one node here is one server with one set of credentials. The rest were dropped, and the servers they described are not reachable through this node.
- Why it happens: Xray lets one outbound hold a list of servers (vnext, servers) or of users, and balances between them itself. A node in the launcher is a single server, so there is no place to put the second entry. Such an element usually comes from a provider that packed several locations, or several accounts, into one outbound.
- What you can do:
- Check that the first entry is the one you need: it is the one that became the node.
- If you need the other servers too, split them into separate elements — one server per outbound.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.
severity: warning · params: value
WireGuard: reserved bytes written as text not applied
- What happened: The element carries the reserved field as the text {value} instead of three numbers. The value was not applied. If the provider requires these bytes, the node completes the handshake but carries no traffic.
- Why it happens: Xray declares the field as a byte string, so the same three bytes may be written either as a list of numbers or as one base64 line, and different panels pick different spellings. The launcher reads the list of numbers, which is the form the core expects; translating the text spelling would need a separate rule that does not exist yet.
- What you can do:
- Ask the provider for the configuration with reserved written as three numbers, for example [1, 2, 3].
- If the node connects but carries no traffic, these bytes are the first thing to check.
Where it comes from:
- Node or subscription level: no field in the registry points at this code, so it is raised while the entry as a whole is being read.