shadowsocks/shadowsocks-rust · error

failed to encode DNS response

Error message

failed to encode DNS response

What it means

In the fake-DNS TCP server, after building a DNS response message the hickory (trust-dns) BinEncoder fails to emit it; the code logs "failed to encode DNS response" and returns the failure as an io::Error (Other). The client connection is closed without a valid DNS reply.

Source

Thrown at crates/shadowsocks-service/src/local/fake_dns/tcp_server.rs:151

                    return Err(io::Error::new(io::ErrorKind::Other, err));
                }
            };

            let rsp_message = match handle_dns_request(&req_message, &manager).await {
                Ok(m) => m,
                Err(err) => {
                    error!("failed to handle DNS request, error: {}", err);

                    Message::error_msg(req_message.id, req_message.op_code, ResponseCode::ServFail)
                }
            };

            let mut rsp_buffer = Vec::with_capacity(2 + 512);
            rsp_buffer.resize(2, 0);
            let mut rsp_encoder = BinEncoder::with_offset(&mut rsp_buffer, 2);
            if let Err(err) = rsp_message.emit(&mut rsp_encoder) {
                error!("failed to encode DNS response, error: {}", err);
                return Err(io::Error::new(io::ErrorKind::Other, err));
            }

            let rsp_length = (rsp_buffer.len() - 2) as u16;
            BigEndian::write_u16(&mut rsp_buffer[0..2], rsp_length);

            stream.write_all(&rsp_buffer).await?;
        }

        Ok(())
    }
}

View on GitHub (pinned to 8eb0f0a65b)

Solutions

  1. Upgrade shadowsocks-service and its hickory-proto dependency to compatible versions
  2. Capture the query causing the failure and reproduce; report/inspect for malformed-input handling
  3. Check logs for the underlying hickory encoder error message for specifics
  4. As a workaround, avoid routing the offending client through fake-dns and use real DNS
Defensive patterns

Strategy: try-catch

Try / catch

// server-side failure surfaces as connection close; on the client side:
match timeout(DNS_TIMEOUT, tcp_dns_query(q)).await {
    Ok(Err(e)) | Err(_) => fallback_to_system_resolver(q).await,
    Ok(Ok(m)) => m,
}

Prevention

When it happens

Trigger: handle_client processes a TCP DNS query, constructs rsp_message, and rsp_message.emit(&mut rsp_encoder) returns an error during wire-format encoding.

Common situations: Malformed or unusual query producing a response that fails encoding; internal bug/incompatible hickory-proto version; buffer/offset issues in the TCP length-prefixed response path.

Related errors


AI-assisted analysis of shadowsocks/shadowsocks-rust@8eb0f0a65b (2026-09-09). Data as JSON: /api/errors/740770a7b73156da. Report an issue: GitHub.