{"record":{"id":"d8ad9fca5545a09d","repo":"vectordotdev/vector","slug":"path-and-query-should-never-fail-to-parse","errorCode":null,"errorMessage":"path and query should never fail to parse","messagePattern":"path and query should never fail to parse","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/sinks/azure_logs_ingestion/service.rs","lineNumber":96,"sourceCode":"    token_scope: String,\n    default_headers: HeaderMap,\n}\n\nimpl AzureLogsIngestionService {\n    /// Creates a new `AzureLogsIngestionService`.\n    pub fn new(\n        client: HttpClient,\n        endpoint: Uri,\n        dcr_immutable_id: String,\n        stream_name: String,\n        credential: Arc<dyn TokenCredential>,\n        token_scope: String,\n    ) -> crate::Result<Self> {\n        let mut parts = endpoint.into_parts();\n        parts.path_and_query = Some(\n            format!(\"/dataCollectionRules/{dcr_immutable_id}/streams/{stream_name}?api-version={API_VERSION}\")\n                .parse()\n                .expect(\"path and query should never fail to parse\"),\n        );\n        let endpoint = Uri::from_parts(parts)?;\n\n        let default_headers = {\n            let mut headers = HeaderMap::new();\n\n            headers.insert(header::CONTENT_TYPE, CONTENT_TYPE_VALUE.clone());\n            headers\n        };\n\n        Ok(Self {\n            client,\n            endpoint,\n            credential,\n            token_scope,\n            default_headers,\n        })\n    }","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/vectordotdev/vector/blob/3708c39b12a93212ed8b8d7510b4cc7769cb5864/src/sinks/azure_logs_ingestion/service.rs#L78-L114","documentation":"The Azure Logs Ingestion sink builds the request path /dataCollectionRules/{dcr_immutable_id}/streams/{stream_name}?api-version=... and parses it as an http PathAndQuery. The expect fires when that string violates the URI grammar because the configured DCR immutable ID or stream name contains characters like spaces, non-ASCII bytes, control characters, or stray percent signs.","triggerScenarios":"Configuring stream_name or dcr_immutable_id with a value such as 'Custom-My Table' (space), a Unicode name, an invalid %-escape, or a trailing newline injected via environment-variable interpolation. DCR immutable IDs are GUID-like and safe, so stream_name is the usual culprit.","commonSituations":"Stream names copied from the Azure Portal with spaces; values injected from env vars containing quotes or newlines; names with % characters forming invalid escapes.","solutions":["Set stream_name to a URI-safe value: letters, digits, '-' and '_' only (Azure convention is Custom-MyTable with no spaces)","Trim whitespace/newlines when injecting values via environment variables (e.g. tr -d '[:space:]')","Validate both fields at config load with regex ^[A-Za-z0-9\\-_.~]+$ and fail fast with a clear error","Percent-encode the stream name before it reaches the sink if special characters are unavoidable"],"exampleFix":"# before\n[sinks.azure]\ntype = \"azure_logs_ingestion\"\nstream_name = \"Custom-My Table\"\n\n# after\n[sinks.azure]\ntype = \"azure_logs_ingestion\"\nstream_name = \"Custom-My_Table\"","handlingStrategy":"validation","validationCode":"fn uri_safe(s: &str) -> bool {\n    !s.is_empty()\n        && s.bytes().all(|b| {\n            b.is_ascii_alphanumeric() || matches!(b, b'-' | b'_' | b'.' | b'~')\n        })\n}\n\nassert!(uri_safe(&stream_name), \"stream_name must be URI-safe\");\nassert!(uri_safe(&dcr_immutable_id), \"DCR immutable ID must be URI-safe\");","typeGuard":"fn is_uri_safe_stream_name(s: &str) -> bool {\n    !s.is_empty()\n        && s.bytes().all(|b| {\n            b.is_ascii_alphanumeric() || matches!(b, b'-' | b'_' | b'.' | b'~')\n        })\n}","tryCatchPattern":null,"preventionTips":["Keep Azure stream names to Custom-[A-Za-z0-9_]+ by convention","Trim env-injected identifiers before they reach config","Add config-lint rules rejecting spaces/non-ASCII in sink identifiers"],"tags":["rust","vector","azure","uri","sink","panic"],"backgroundTag":"uri-parse-failed","analyzedSha":"3708c39b12a93212ed8b8d7510b4cc7769cb5864","analyzedAt":"2026-08-20T07:02:18.786Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}