vectordotdev/vector · critical

valid message key

Error message

valid message key

What it means

Panic via `.expect("valid message key")` in the syslog deserializer's `schema_definition` (lib/codecs/src/decoding/format/syslog.rs). The deserializer declares the schema for the standard `message` field using the global log schema's configured key, but `log_schema().message_key()` is an `Option`: when the deployment's global `[log_schema]` config sets `message_key = ""` (unset), it returns `None` and building the schema definition panics. The syslog decoder fundamentally assumes a message key exists, because on parse failure the entire body becomes the message.

Source

Thrown at lib/codecs/src/decoding/format/syslog.rs:69

            source: self.source,
            lossy: self.syslog.lossy,
        }
    }

    /// Return the type of event build by this deserializer.
    pub fn output_type(&self) -> DataType {
        DataType::Log
    }

    /// The schema produced by the deserializer.
    pub fn schema_definition(&self, log_namespace: LogNamespace) -> schema::Definition {
        match (log_namespace, self.source) {
            (LogNamespace::Legacy, _) => {
                let mut definition = schema::Definition::empty_legacy_namespace()
                    // The `message` field is always defined. If parsing fails, the entire body becomes the
                    // message.
                    .with_event_field(
                        log_schema().message_key().expect("valid message key"),
                        Kind::bytes(),
                        Some("message"),
                    );

                if let Some(timestamp_key) = log_schema().timestamp_key() {
                    // All other fields are optional.
                    definition = definition.optional_field(
                        timestamp_key,
                        Kind::timestamp(),
                        Some("timestamp"),
                    )
                }

                definition = definition
                    .optional_field(&owned_value_path!("hostname"), Kind::bytes(), Some("host"))
                    .optional_field(
                        &owned_value_path!("severity"),
                        Kind::bytes(),

View on GitHub (pinned to 3708c39b12)

Solutions

  1. Set a non-empty message key in the global log schema: `[log_schema] message_key = "msg"`
  2. Or remove the `message_key = ""` override entirely to restore the default `message`
  3. If you truly need no message key, don't use the syslog source/codec — decode with a codec that doesn't assume one

Example fix

# before
[log_schema]
message_key = ""

[sources.in]
type = "syslog"

# after
[log_schema]
message_key = "message"

[sources.in]
type = "syslog"
Defensive patterns

Strategy: validation

Validate before calling

// Guard before using the syslog codec: global log schema must have a message key
use vector_core::config::log_schema;
assert!(
    log_schema().message_key().is_some(),
    "syslog codec requires a non-empty log_schema.message_key"
);

Prevention

When it happens

Trigger: Running with a `syslog` source (or the syslog codec) while the global config contains `[log_schema] message_key = ""`. The panic fires when the codec's schema definition is queried (config build/startup or schema inspection), not per event.

Common situations: Operators disabling the default `message` key globally (e.g. to normalize schemas for a downstream that forbids it), then adding a syslog source; test setups with a minimal global config that clears standard keys.

Related errors


AI-assisted analysis of vectordotdev/vector@3708c39b12 (2026-08-20). Data as JSON: /api/errors/6602d1e2247813d7. Report an issue: GitHub.