{"record":{"id":"8e0dc7ad90d67aaf","repo":"vectordotdev/vector","slug":"max-decompressed-size-bytes-already-set","errorCode":null,"errorMessage":"max_decompressed_size_bytes already set","messagePattern":"max_decompressed_size_bytes already set","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"lib/vector-common/src/decompression.rs","lineNumber":79,"sourceCode":"        .saturating_div(1000)\n        .saturating_add(11) as usize\n}\n\nconst DEFAULT_MAX_ZLIB_COMPRESSED_FRAME_SIZE_BYTES: usize =\n    zlib_compressed_frame_limit(DEFAULT_MAX_DECOMPRESSED_SIZE_BYTES);\n\nconst DEFAULT_MAX_ZSTD_WINDOW_LOG: Option<u32> =\n    zstd_window_log_max(DEFAULT_MAX_DECOMPRESSED_SIZE_BYTES);\n\n/// Override the global decompressed payload size cap. Must be called before any sources start.\n///\n/// # Panics\n///\n/// Panics if called more than once, as the global cap may only be initialized a single time.\npub fn set_max_decompressed_size_bytes(size: usize) {\n    MAX_DECOMPRESSED_SIZE_BYTES\n        .set(size)\n        .expect(\"max_decompressed_size_bytes already set\");\n    MAX_ZLIB_COMPRESSED_FRAME_SIZE_BYTES\n        .set(zlib_compressed_frame_limit(size))\n        .expect(\"max_zlib_compressed_frame_size_bytes already set\");\n    MAX_ZSTD_WINDOW_LOG\n        .set(zstd_window_log_max(size))\n        .expect(\"max_zstd_window_log already set\");\n}\n\n/// Returns the currently configured decompressed payload size cap.\npub fn max_decompressed_size_bytes() -> usize {\n    *MAX_DECOMPRESSED_SIZE_BYTES\n        .get()\n        .unwrap_or(&DEFAULT_MAX_DECOMPRESSED_SIZE_BYTES)\n}\n\n/// Returns the maximum compressed frame wire size we are willing to buffer, derived from the\n/// decompressed cap plus zlib's worst-case expansion. See `zlib_compressed_frame_limit`.\npub fn max_zlib_compressed_frame_size_bytes() -> usize {","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/vectordotdev/vector/blob/3708c39b12a93212ed8b8d7510b4cc7769cb5864/lib/vector-common/src/decompression.rs#L61-L97","documentation":"vector-common keeps the global decompression-size cap (used by all sources/decoders to stop decompression bombs) in a std::sync::OnceLock. `set_max_decompressed_size_bytes` initializes that cap plus two derived limits and is documented to be called exactly once, before any sources start. Calling it a second time makes OnceLock::set return Err, and this expect panics with 'max_decompressed_size_bytes already set'.","triggerScenarios":"Calling vector_common::decompression::set_max_decompressed_size_bytes twice in one process — e.g. a test harness that initializes per test without a once-guard, or two embedded components (CLI flag handler plus app init) both configuring the cap.","commonSituations":"Embedding Vector crates as a library; integration/cargo test suites where every test calls setup; refactors that moved the init call so it now runs on both the CLI path and the library path.","solutions":["Call set_max_decompressed_size_bytes exactly once, at process start, before spawning any sources","Wrap the initialization in std::sync::Once or a OnceLock<()> in your own setup helper so repeat calls become no-ops","In test suites, move the call to a shared once-per-process helper (one #[ctor] or the first line of a common fixture) instead of per-test setup"],"exampleFix":"// before: panics when setup() runs twice\nfn setup(size: usize) {\n    vector_common::decompression::set_max_decompressed_size_bytes(size);\n}\n\n// after: idempotent\nstatic INIT: std::sync::Once = std::sync::Once::new();\nfn setup(size: usize) {\n    INIT.call_once(|| {\n        vector_common::decompression::set_max_decompressed_size_bytes(size);\n    });\n}","handlingStrategy":"validation","validationCode":"static INIT: std::sync::Once = std::sync::Once::new();\n\nfn init_decompression_cap(size: usize) {\n    INIT.call_once(|| {\n        vector_common::decompression::set_max_decompressed_size_bytes(size);\n    });\n}","typeGuard":null,"tryCatchPattern":"let result = std::panic::catch_unwind(|| {\n    set_max_decompressed_size_bytes(size);\n});\nif result.is_err() {\n    // already initialized earlier in this process; safe to ignore in test harnesses\n}","preventionTips":["Initialize the cap exactly once at process start, before any sources start (per the API docs)","Guard the call with std::sync::Once or a OnceLock in your own setup so repeat calls are no-ops","In cargo test suites, use one shared once-per-process fixture rather than per-test setup calls","Note the getters return the default when unset, so you cannot reliably probe set-ness afterwards — enforce the once rule structurally instead"],"tags":["rust","vector","decompression","global-state","oncelock","panic"],"backgroundTag":"oncelock-already-initialized","analyzedSha":"3708c39b12a93212ed8b8d7510b4cc7769cb5864","analyzedAt":"2026-08-20T07:02:18.786Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}