{"record":{"id":"1fe77a1bb84c0f7a","repo":"neondatabase/neon","slug":"invalid-host-format-for-postgres-logs-export","errorCode":null,"errorMessage":"Invalid host format for Postgres logs export","messagePattern":"Invalid host format for Postgres logs export","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compute_tools/src/rsyslog.rs","lineNumber":211,"sourceCode":"\nimpl<'a> PostgresLogsRsyslogConfig<'a> {\n    pub fn new(host: Option<&'a str>) -> Self {\n        Self { host }\n    }\n\n    pub fn build(&self) -> Result<String> {\n        match self.host {\n            Some(host) => {\n                if let Some((target, port)) = host.split_once(\":\") {\n                    Ok(format!(\n                        include_str!(\n                            \"config_template/compute_rsyslog_postgres_export_template.conf\"\n                        ),\n                        logs_export_target = target,\n                        logs_export_port = port,\n                    ))\n                } else {\n                    Err(anyhow!(\"Invalid host format for Postgres logs export\"))\n                }\n            }\n            None => Ok(\"\".to_string()),\n        }\n    }\n\n    fn current_config() -> Result<String> {\n        let config_content = match std::fs::read_to_string(POSTGRES_LOGS_CONF_PATH) {\n            Ok(c) => c,\n            Err(err) if err.kind() == ErrorKind::NotFound => String::new(),\n            Err(err) => return Err(err.into()),\n        };\n        Ok(config_content)\n    }\n}\n\n/// Writes rsyslogd configuration for Postgres logs export and restarts rsyslog.\npub fn configure_postgres_logs_export(conf: PostgresLogsRsyslogConfig) -> Result<()> {","sourceCodeStart":193,"sourceCodeEnd":229,"githubUrl":"https://github.com/neondatabase/neon/blob/8f60b04da47ffefe0e52bda2440134b42874eb75/compute_tools/src/rsyslog.rs#L193-L229","documentation":"PostgresLogsRsyslogConfig::build received Some(host) from the spec's logs_export_host field, but host.split_once(':') found no colon, so there is no host/port pair to substitute into the rsyslog forwarding template. Unlike parse_audit_syslog_address, this path only requires one colon - no deeper URL validation happens. configure_postgres_logs_export propagates the error (compute.rs uses `?`), failing compute configuration.","triggerScenarios":"The control-plane spec carries logs_export_host without a colon, e.g. \"invalid\" or a bare hostname; the unit test test_postgres_logs_config encodes exactly this rejection.","commonSituations":"Setting the endpoint's log export destination in the console/API to a hostname without a port; unbracketed IPv6 values whose colons are consumed oddly; hand-edited specs.","solutions":["Set logs_export_host in the control plane as host:port, e.g. collector.cvc.local:514","After fixing the value, re-attach or reconfigure the compute so the new spec is fetched","Validate the format at the control plane before it reaches compute_ctl"],"exampleFix":"// before\nlet conf = PostgresLogsRsyslogConfig::new(Some(\"invalid\"));\n\n// after\nlet conf = PostgresLogsRsyslogConfig::new(Some(\"collector.cvc.local:514\"));","handlingStrategy":"validation","validationCode":"// guard the spec field before building the config\nlet host = match spec.logs_export_host.as_deref() {\n    Some(h) if h.split_once(':').is_some() => Some(h),\n    other => {\n        tracing::warn!(\"ignoring malformed logs_export_host: {other:?}\");\n        None\n    }\n};\nlet conf = PostgresLogsRsyslogConfig::new(host);","typeGuard":"fn is_host_port_pair(host: &str) -> bool {\n    matches!(host.split_once(':'), Some((h, p)) if !h.is_empty() && p.parse::<u16>().is_ok())\n}","tryCatchPattern":"match self.host {\n    Some(host) if host.split_once(':').is_some() => { /* build template */ }\n    Some(host) => return Err(anyhow!(\"Invalid host format for Postgres logs export: {host}\")),\n    None => Ok(String::new()),\n}","preventionTips":["Enforce host:port format for logs_export_host at the control plane before it reaches computes","Unit-test PostgresLogsRsyslogConfig::build for every value shape you ship","Reject IPv6-without-brackets values at ingestion"],"tags":["rsyslog","logs-export","host-port","validation","rust"],"backgroundTag":"invalid-host-port-format","analyzedSha":"8f60b04da47ffefe0e52bda2440134b42874eb75","analyzedAt":"2026-08-16T23:39:28.135Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}