{"record":{"id":"34ccf1e36f8426af","repo":"nikivdev/code","slug":"flow-codex-maple-traces-endpoints-count-does","errorCode":null,"errorMessage":"FLOW_CODEX_MAPLE_TRACES_ENDPOINTS count ({}) does not match FLOW_CODEX_MAPLE_INGEST_KEYS count ({})","messagePattern":"FLOW_CODEX_MAPLE_TRACES_ENDPOINTS count \\((.+?)\\) does not match FLOW_CODEX_MAPLE_INGEST_KEYS count \\((.+?)\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/codex_telemetry.rs","lineNumber":285,"sourceCode":"        env_non_empty_with_store(\"FLOW_CODEX_MAPLE_TRACES_ENDPOINTS\", &mut personal_env)\n            .map(|raw| {\n                raw.split(',')\n                    .map(|value| value.trim().to_string())\n                    .filter(|value| !value.is_empty())\n                    .collect::<Vec<_>>()\n            })\n            .unwrap_or_default();\n    let csv_keys = env_non_empty_with_store(\"FLOW_CODEX_MAPLE_INGEST_KEYS\", &mut personal_env)\n        .map(|raw| {\n            raw.split(',')\n                .map(|value| value.trim().to_string())\n                .filter(|value| !value.is_empty())\n                .collect::<Vec<_>>()\n        })\n        .unwrap_or_default();\n    if !csv_endpoints.is_empty() || !csv_keys.is_empty() {\n        if csv_endpoints.len() != csv_keys.len() {\n            anyhow::bail!(\n                \"FLOW_CODEX_MAPLE_TRACES_ENDPOINTS count ({}) does not match FLOW_CODEX_MAPLE_INGEST_KEYS count ({})\",\n                csv_endpoints.len(),\n                csv_keys.len()\n            );\n        }\n        for (endpoint, key) in csv_endpoints.into_iter().zip(csv_keys.into_iter()) {\n            targets.push(MapleIngestTarget {\n                traces_endpoint: endpoint,\n                ingest_key: key,\n            });\n        }\n    }\n\n    if targets.is_empty() {\n        return Ok(None);\n    }\n\n    targets.dedup_by(|a, b| a.traces_endpoint == b.traces_endpoint && a.ingest_key == b.ingest_key);","sourceCodeStart":267,"sourceCodeEnd":303,"githubUrl":"https://github.com/nikivdev/code/blob/a747e741ae92c09071d0ae946ab48488adcff1ce/src/codex_telemetry.rs#L267-L303","documentation":"The exporter also supports multiple ingest targets via two comma-separated lists: `FLOW_CODEX_MAPLE_TRACES_ENDPOINTS` and `FLOW_CODEX_MAPLE_INGEST_KEYS`. Each endpoint needs exactly one key, so if the filtered (non-empty) lists differ in length the parser bails with both counts. This guarantees endpoint/key pairing is never implicit.","triggerScenarios":"Calling `status`/`flush` where the two CSV env vars produce different numbers of non-empty entries after splitting on commas and filtering empty items.","commonSituations":"Adding a third endpoint but forgetting its key; trailing commas creating an implicit empty entry counted on one side only; whitespace-only entries removed by the filter on one list; stale counts after rotating keys.","solutions":["Make both CSV lists contain the same number of comma-separated, non-empty values","Remove trailing commas and stray empty entries from either list","Pair-check manually: split both on ',' and compare counts before exporting the env"],"exampleFix":"// before\nFLOW_CODEX_MAPLE_TRACES_ENDPOINTS=http://a:7281,http://b:7281,\nFLOW_CODEX_MAPLE_INGEST_KEYS=key-a\n# after (2 endpoints, 2 keys, no trailing comma)\nFLOW_CODEX_MAPLE_TRACES_ENDPOINTS=http://a:7281,http://b:7281\nFLOW_CODEX_MAPLE_INGEST_KEYS=key-a,key-b","handlingStrategy":"validation","validationCode":"fn csv_counts_match() -> bool {\n    let n = |name: &str| std::env::var(name).ok()\n        .map(|v| v.split(',').map(str::trim).filter(|s| !s.is_empty()).count())\n        .unwrap_or(0);\n    let (e, k) = (n(\"FLOW_CODEX_MAPLE_TRACES_ENDPOINTS\"), n(\"FLOW_CODEX_MAPLE_INGEST_KEYS\"));\n    (e == 0 && k == 0) || e == k\n}\nassert!(csv_counts_match(), \"TRACES_ENDPOINTS and INGEST_KEYS must list equal non-empty counts\");","typeGuard":"fn zip_csv_pairs<'a>(endpoints: &'a str, keys: &'a str) -> Option<Vec<(&'a str, &'a str)>> {\n    let e: Vec<_> = endpoints.split(',').map(str::trim).filter(|s| !s.is_empty()).collect();\n    let k: Vec<_> = keys.split(',').map(str::trim).filter(|s| !s.is_empty()).collect();\n    (e.len() == k.len()).then(|| e.into_iter().zip(k).collect())\n}","tryCatchPattern":"match telemetry::status() {\n    Err(e) if e.to_string().contains(\"does not match\") => {\n        eprintln!(\"{} — align FLOW_CODEX_MAPLE_TRACES_ENDPOINTS with FLOW_CODEX_MAPLE_INGEST_KEYS\", e);\n        Err(e)\n    }\n    other => other,\n}","preventionTips":["Edit both CSV lists together and always add endpoint+key as a pair","Avoid trailing commas and whitespace-only entries in the CSV values","Keep the list definition in one templated file so counts can never drift"],"tags":["telemetry","env","config","maple"],"backgroundTag":"env-var-count-mismatch","analyzedSha":"a747e741ae92c09071d0ae946ab48488adcff1ce","analyzedAt":"2026-09-01T22:43:55.719Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}