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
- Set a non-empty message key in the global log schema: `[log_schema] message_key = "msg"`
- Or remove the `message_key = ""` override entirely to restore the default `message`
- 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
- Never set [log_schema] message_key = "" in deployments that use the syslog source/codec
- Regression-test custom global log_schema configs together with syslog sources
- Treat 'codec assumes a standard key' as a contract when renaming global schema keys
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
- registered log schema required
- path and query should never fail to parse
- Serializer does not support JSON
- Paths must always start with a leading forward slash (`/`).
- Only leaf nodes should be allowed to be non-object values.
AI-assisted analysis of vectordotdev/vector@3708c39b12 (2026-08-20).
Data as JSON: /api/errors/6602d1e2247813d7.
Report an issue: GitHub.