Router Troubleshooting Guide

March 17, 2026 · View on GitHub

简体中文

Router Troubleshooting Guide

This document is based on the Golang Router implementation and summarizes common log messages, response outputs, and troubleshooting methods encountered during Router usage, helping users quickly locate and resolve issues.

For basic Router usage, please refer to Load-Balancing Scheduling Router.

Common Log Analysis

Note: {} represents variables that will be replaced with actual values in logs.

Error-Level Logs

Log MessageMeaningImpactWhat to Check
Removed unhealthy prefill instance: {url}Prefill instance failed health check and has been removedThis Prefill instance will no longer participate in schedulingHealth status
Removed unhealthy decode instance: {url}Decode instance failed health check and has been removedThis Decode instance will no longer participate in schedulingHealth status
Removed unhealthy mixed instance: {url}Mixed instance failed health check and has been removedThis Mixed instance will no longer participate in schedulingHealth status
Failed to register instance: {error}Instance registration failedRouter cannot register the instanceHealth status, registration parameters
Failed to read YAML file {path}: {error}Failed to read registration config file at startupInstances in the config file cannot be registeredFile path, file permissions
Failed to unmarshal YAML file {path}: {error}Registration config file has invalid formatInstances in the config file cannot be registeredYAML format
Failed to register instance from index {index}: {error}Instance at index {index} in config file failed to registerThat instance was not registeredHealth status, registration parameters
failed to send request to {url} with error: {error}Health check request failed to sendThe instance may be marked as unhealthyNetwork connectivity, proxy settings
scanner error: {error}Error occurred while reading backend streaming responseThe current request may failBackend instance status
[prefill] scanner error: {error}, message={message}Error occurred while reading Prefill backend streaming responseThe current Prefill request may failBackend instance status
[prefill] copy error: {error}, message={message}Error occurred while copying Prefill response dataThe current Prefill request may failBackend instance status
Panic recovered: {error}A panic occurred during request processing and was recoveredThe current request fails, but the service continues runningBackend instance status, request content
empty baseURL providedHealth check received an empty base URLHealth check cannot be performedRegistration parameters
failed to create request: {error}Failed to create health check requestThe instance may be marked as unhealthyNetwork environment
failed to read response body: {error}Failed to read health check response bodyThe instance may be marked as unhealthyBackend instance status

Warn-Level Logs

Log MessageMeaningImpactWhat to Check
Server {url} is not healthyThe instance at this URL failed health checkRouter cannot register the instance, or will remove it from the registered listHealth status
Instance {url} role is unknownInstance role cannot be recognizedThe instance will not be added to the scheduling listRegistration parameters
cache-aware prefill: tokenizer failed, fallback to char tokens: {error}Tokenizer service call failed, automatically falling back to character-based tokenizationcache_aware strategy remains active, using character-based tokenization for cache matching instead of the Tokenizer; normal request processing is not affectedTokenizer service status
cache-aware prefill: tokenize failed, fallback to process_tokens: {error}Tokenization completely failed (e.g., empty input), falling back to process_tokens strategyPrefill scheduling temporarily does not use cache_aware strategy; normal request processing is not affectedRequest content, Tokenizer service status
cache-aware prefill: final strategy: process_tokens, reason: tokenize failed: {error}. ts_ms={ts}Tokenization failed (new format), falling back to process_tokens strategyPrefill scheduling temporarily does not use cache_aware strategy; normal request processing is not affectedRequest content, Tokenizer service status

Info-Level Logs

Log MessageMeaningDescription
Starting server on {host:port}Router service is startingNormal startup log
Server {url} is healthyInstance passed health checkNormal operation log
Successfully registered instance from index {index}Instance from config file registered successfullyNormal startup log
No instances found in config file {path}No instances found in the registration config fileCheck whether register.yaml is empty
Request completed successfully.Request processing completedNormal operation log
Request failed, retrying...Request failed, retryingRouter will retry up to 3 times
select worker (prefill): {url}, tokens: {tokens}Prefill scheduler selected a worker, showing current token processing countNormal operation log
select worker ({type}): {url}, count: {count}Decode/Mixed scheduler selected a worker, showing current request concurrencyNormal operation log
release worker: {url}, count: {count}Request ended, worker counter releasedNormal operation log
release prefill tokens: {url}, tokens: {tokens}Prefill request ended, token load releasedNormal operation log
cleanup unhealthy worker counter: {url}Cleaned up counter for unhealthy workerNormal operation log
removed counters for {count} unhealthy workers: {urls}Batch cleanup of counters for unhealthy workersNormal operation log
[stats] total_running={n}, workers: [{loads}], cache_hit_rate={rate}% (hits={hits}/total={total})Periodic stats: total requests, worker loads, cache hit rateNormal operation log, useful for monitoring and tuning
Parsing completed; starting worker selection.Request parsing completed, starting worker selectionNormal operation log
Request completed with an error.Request processing completed with an errorCheck backend instance status
[SelectWorkerPair] decode selection failed, releasing prefill counter url={url}Decode selection failed in PD disaggregated mode, releasing Prefill counterError handling log
[prefill] first chunk received, release counter url={url}Prefill streaming response received first chunk, counter releasedNormal operation log
[prefill] non-stream prefill response done, release counter url={url}Prefill non-streaming response completed, counter releasedNormal operation log
[prefill] backendResp is nil or backendResp.Body is nil, url={url}Prefill backend response is nilMay indicate backend connection issue
[prefill] release in defer (fallback) url={url}, isStream={bool}Fallback resource release when Prefill request exits abnormallyError handling log
[prefill] release in CommonCompletions defer (error path) url={url}Prefill resource release on error pathError handling log
cache-aware prefill: final strategy: process_tokens, reason: strategy not initializedcache_aware strategy not initialized, falling back to process_tokensCheck cache_aware configuration
cache-aware prefill: final strategy: process_tokens, reason: load imbalanced, loads={loads}. ts_ms={ts}Load imbalanced across instances, falling back to process_tokens strategyNormal operation log, automatic load balancing switch
cache-aware prefill: final strategy: cache_aware_scoring, selected={url}, loads={loads}, hitRatios={ratios}. ts_ms={ts}cache_aware scoring strategy selected a workerNormal operation log, showing loads and hit ratios
[{method}] {path} {proto} {status} {latency} {clientIP}HTTP request access logNormal operation log, records basic info for each request
before SelectWorker prefill. ts_ms={ts}Starting Prefill worker selection in PD disaggregated modeNormal operation log, for performance tracing
before SelectWorker decode, after prefill. ts_ms={ts}Starting Decode worker selection after Prefill selectionNormal operation log, for performance tracing
after SelectWorker decode, before return. ts_ms={ts}Decode worker selection completedNormal operation log, for performance tracing

Debug-Level Logs

Debug-level logs are only output when the log level is set to debug, typically used for development debugging.

Log MessageMeaningDescription
Healthy instances: prefill={urls}, decode={urls}, mixed={urls}Lists healthy instances for each roleUseful for verifying instance discovery
cache-aware prefill: hashes={n} workers={n} load={loads} hit={hits}Hash count, worker count, and load info for cache_aware strategyUseful for debugging cache hits
cache-aware prefill: tokenizer tokens={tokens}Tokenizer tokenization resultUseful for debugging tokenization results
cache-aware score: worker={url} hit={hit} loadRatio={ratio} score={score}Scoring details for cache_aware strategyUseful for debugging scheduling decisions
radix match: hashes={n} matched_len={n} node_children={n}Radix tree match detailsUseful for debugging cache matching
radix record: worker={url} hashes={n} node_depth={n}Radix tree record detailsUseful for debugging cache recording
radix eviction: removed={n} nodeCount={n}Radix tree eviction detailsUseful for debugging cache eviction

Common Response Output Analysis

Inference Request Errors (/v1/chat/completions, /v1/completions)

OutputHTTP StatusMeaningWhat to Check
{"error": "No available prefill/decode workers"}503All Prefill or Decode instances are unavailable, no registered healthy instancesHealth status
{"error": "Failed to select worker pair"}502Failed to select a worker pair in PD disaggregated modeHealth status, scheduling strategy
{"error": "Failed to select worker"}502Failed to select a worker in centralized modeHealth status, scheduling strategy
{"error": "Failed to connect to backend service"}502Failed to connect to backend inference instance (after 3 retries)Backend instance status, network connectivity
{"error": "Failed to build disaggregate_info"}500Failed to build PD disaggregation communication infoRegistration parameters (connector_port, device_ids, etc.)
{"error": "Invalid request body"}400Failed to read request bodyRequest format
{"error": "Invalid JSON format"}400Failed to parse request body JSONRequest format

Registration Request Errors (/register)

OutputHTTP StatusMeaningWhat to Check
{"code": 503, "msg": "{url} service is not healthy"}503Instance failed health check, cannot be registeredHealth status
{"code": 400, "msg": "Invalid request body"}400Failed to read registration request bodyRequest format
{"code": 400, "msg": "Invalid InstanceInfo JSON format: {error}"}400Registration request has invalid JSON formatRequest format
{"code": 400, "msg": "splitwise mode only supports PREFILL/DECODE instances"}400MIXED instances are not allowed in PD disaggregated modeDeployment mode, instance role
{"code": 400, "msg": "only MIXED instances are allowed"}400Only MIXED instances are allowed in centralized modeDeployment mode, instance role
{"code": 400, "msg": "invalid InstanceInfo format: {error}"}400Instance registration info validation failedRegistration parameters
{"code": 200, "msg": "Register success"}200Registration successful

Common Registration Parameter Validation Errors

Error MessageMeaningSolution
role is requiredMissing role fieldAdd the role field with value: prefill / decode / mixed
invalid role: {role}Invalid role valueUse a valid role value: prefill / decode / mixed
host_ip is requiredMissing host_ip fieldAdd the host_ip field
invalid host_ip: {ip}host_ip is not a valid IP addressProvide a valid IP address
port is requiredMissing port fieldAdd the port field
invalid port: {port}port is not a valid port numberProvide a port number in the range 1-65535
invalid protocol: {protocol}Invalid transfer protocolUse a valid protocol value: ipc / rdma

Troubleshooting Guide

Health Status

Instance health checking is fundamental to Router operation. When instances fail to register or are removed, follow these steps:

1. Check instance registration status

View the currently registered instances and their count:

# View registered instance list
curl -X GET http://{router_url}/registered

# View registered instance count
curl -X GET http://{router_url}/registered_number

Verify that all expected instances are registered. If the count does not match, some instances may have failed to register or been removed by health checks.

2. Check instance health and network connectivity

Directly access the inference instance's health endpoint from the Router's host:

curl -X GET http://{server_url}/health
  • HTTP 200 response indicates the instance is healthy and the network is reachable
  • If unreachable or returning a non-200 status code, investigate further:
    • Whether the instance is started and listening on the correct port
    • Whether a proxy is interfering with the connection (try disabling: unset http_proxy && unset https_proxy)
    • Whether firewall rules are blocking the connection

Common solutions:

  • Disable network proxy: unset http_proxy && unset https_proxy
  • gunicorn version compatibility: If registered instance count is incomplete, it may be due to gunicorn and FastDeploy version incompatibility. Downgrading to gunicorn==25.0.3 can resolve this issue

Scheduling Strategy

When encountering Failed to select worker or Failed to select worker pair errors:

1. Verify registered instance count

curl -X GET http://{router_url}/registered_number

If the returned count is 0, there are no available healthy instances. Please refer to Health Status for troubleshooting.

2. Check scheduling strategy configuration

Verify that the scheduling strategy in config.yaml matches your deployment mode. The default scheduling strategies are:

Deployment ModeConfig FieldDefault Strategy
Centralized modepolicyrequest_num
PD disaggregated mode (Prefill)prefill-policyprocess_tokens
PD disaggregated mode (Decode)decode-policyrequest_num

If no strategy is specified in the config file, the Router will use the defaults listed above. To use advanced strategies such as cache_aware or fd_metrics_score, specify them explicitly in the config file. For detailed descriptions of each strategy, see Scheduling Strategies.

3. Check fd_metrics_score strategy dependencies

When using the fd_metrics_score strategy, the Router fetches running/waiting request counts in real time from the /metrics endpoint of inference instances. When the /metrics endpoint is unavailable (e.g., metrics_port is not configured or the metrics service is down), the Router automatically falls back to the internal request counter for scheduling. This does not affect normal request processing, but scheduling accuracy may be reduced.

To ensure optimal scheduling with fd_metrics_score, verify that the inference instance's metrics endpoint is responding correctly:

curl -X GET http://{server_url}/metrics

Registration Parameters

When registration fails with parameter validation errors:

1. Verify deployment mode and instance role match

  • PD disaggregated mode (--splitwise): Only prefill and decode roles can be registered
  • Centralized mode (default): Only mixed role can be registered

2. Check required parameters

Registration requests must include the following fields:

  • role: Instance role (prefill / decode / mixed)
  • host_ip: Instance IP address
  • port: Instance port number

3. Check optional parameters for PD disaggregated mode

In PD disaggregated mode, the following parameters should be fully configured to ensure proper KV Cache transfer:

  • connector_port: PD communication port
  • transfer_protocol: Transfer protocol (ipc / rdma)
  • device_ids: GPU device IDs
  • rdma_ports: RDMA ports (required when using the rdma protocol)

Startup Failures

1. Configuration file loading failure

If Failed to load config appears in startup logs, check:

  • Whether the file path specified by --config_path is correct
  • Whether the configuration file is valid YAML
  • Whether configuration parameter values are valid

2. Port already in use

If Failed to start server appears in startup logs, check:

  • Whether the port specified by --port is already occupied by another process
  • Use lsof -i:{port} or netstat -tlnp | grep {port} to check port usage

Tokenizer Service (cache_aware Strategy)

When using the cache_aware scheduling strategy, the Router calls a Tokenizer service to tokenize requests for cache hit ratio computation. When the Tokenizer service is unavailable, the Router has a two-level degradation mechanism:

  1. Fallback to character-based tokenization (common case): The log will show tokenizer failed, fallback to char tokens. The cache_aware strategy remains active, using character-based tokenization for cache matching instead of the Tokenizer. Cache hit accuracy may decrease, but normal request processing is not affected.
  2. Fallback to process_tokens strategy (extreme case): When tokenization completely fails (e.g., empty request content), the log will show tokenize failed, fallback to process_tokens. The cache_aware strategy temporarily becomes inactive, and scheduling falls back to token processing volume. Normal request processing is not affected.

To restore full cache_aware functionality:

1. Check if the Tokenizer service is running

curl -X POST http://{tokenizer_url}/tokenize \
  -H "Content-Type: application/json" \
  -d '{"text": "hello"}'

2. Check related configuration

  • Verify that tokenizer-url in config.yaml is set correctly
  • If the Tokenizer service responds slowly, consider increasing tokenizer-timeout-secs (default: 2 seconds)