vectordotdev/vector · error · LinesCodecError

Unable to decode message len as number

Error message

Unable to decode message len as number

What it means

The octet counting framer reads a leading decimal length prefix followed by a space. This error is raised when the bytes before the first space cannot be parsed as a valid number (the length prefix is not a sensible integer), so the framer cannot determine the message length. The parser advances past the bad bytes to avoid an infinite loop.

Solutions

  1. Fix the sender to emit the octet-counting format: ASCII decimal byte count, one space, then the payload.
  2. Change the Vector source's framing to match the actual sender format (e.g. newline_delimited).
  3. Inspect what is actually arriving on the socket (tcpdump/tcpreceive) to identify the mismatch.

Example fix

// before (sender)
"hello world\n"
// after (octet counting)
"11 hello world"
Defensive patterns

Strategy: validation

Validate before calling

// verify sender emits octet counting format before shipping
fn looks_like_octet_frame(buf: &[u8]) -> bool {
    match buf.iter().position(|&b| b == b' ') {
        Some(sp) => buf[..sp].iter().all(|b| b.is_ascii_digit()),
        None => false,
    }
}

Try / catch

match framed_stream.next().await {
    Err(e) if e.kind() == ErrorKind::InvalidData => {
        // wrong framing: log a sample of raw bytes and reconfigure
    }
    other => other?,
}

Prevention

When it happens

Trigger: Sending data over a TCP stream whose first token is not a decimal length followed by a space; a sender using a different framing protocol (e.g. newline-delimited or syslog) pointed at an octet-counting configured source; corrupted/partial data at the start of the stream.

Common situations: Mixing up framing configs between producers and consumers (producer sends plain lines, consumer expects <len> SP <message>); binary or garbage data hitting the port; a load balancer injecting non-protocol data.

Understand the failure class

Related errors


AI-assisted analysis of vectordotdev/vector@bdb87aeaa4 (2026-09-16). Data as JSON: /api/errors/d22658c3d6a39a44. Report an issue: GitHub.

Appendix: source

Thrown at lib/codecs/src/decoding/framing/octet_counting.rs:150

            (State::NotDiscarding, _, Some(space_pos)) if space_pos < self.other.max_length() => {
                // Everything looks good.
                //
                // We aren't discarding, we have a space that is not beyond our
                // maximum length. Attempt to parse the bytes as a number which
                // will hopefully give us a sensible length for our message.
                let len: usize = match std::str::from_utf8(&src[..space_pos])
                    .map_err(|_| ())
                    .and_then(|num| num.parse().map_err(|_| ()))
                {
                    Ok(len) => len,
                    Err(_) => {
                        // It was not a sensible number.
                        //
                        // Advance the buffer past the erroneous bytes to
                        // prevent us getting stuck in an infinite loop.
                        src.advance(space_pos + 1);
                        self.octet_decoding = None;
                        return Err(LinesCodecError::Io(io::Error::new(
                            io::ErrorKind::InvalidData,
                            "Unable to decode message len as number",
                        )));
                    }
                };

                let from = space_pos + 1;
                let to = from + len;

                if len > self.other.max_length() {
                    // The length is greater than we want.
                    //
                    // We need to discard the entire message.
                    self.octet_decoding = Some(State::Discarding(len));
                    src.advance(space_pos + 1);

                    Ok(None)
                } else if let Some(msg) = src.get(from..to) {

View on GitHub (pinned to bdb87aeaa4)