{"record":{"id":"c13873a706d1efe9","repo":"neondatabase/neon","slug":"library-is-not-found","errorCode":null,"errorMessage":"library {} is not found","messagePattern":"library (.+?) is not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"libs/compute_api/src/spec.rs","lineNumber":403,"sourceCode":"    pub fn get_ext(\n        &self,\n        ext_name: &str,\n        is_library: bool,\n        build_tag: &str,\n        pg_major_version: &str,\n    ) -> anyhow::Result<(String, RemotePath)> {\n        let mut real_ext_name = ext_name;\n        if is_library {\n            // sometimes library names might have a suffix like\n            // library.so or library.so.3. We strip this off\n            // because library_index is based on the name without the file extension\n            let strip_lib_suffix = Regex::new(r\"\\.so.*\").unwrap();\n            let lib_raw_name = strip_lib_suffix.replace(real_ext_name, \"\").to_string();\n\n            real_ext_name = self\n                .library_index\n                .get(&lib_raw_name)\n                .ok_or(anyhow::anyhow!(\"library {} is not found\", lib_raw_name))?;\n        }\n\n        // Check if extension is present in public or custom.\n        // If not, then it is not allowed to be used by this compute.\n        if !self\n            .public_extensions\n            .as_ref()\n            .is_some_and(|exts| exts.iter().any(|e| e == real_ext_name))\n            && !self\n                .custom_extensions\n                .as_ref()\n                .is_some_and(|exts| exts.iter().any(|e| e == real_ext_name))\n        {\n            return Err(anyhow::anyhow!(\"extension {} is not found\", real_ext_name));\n        }\n\n        match self.extension_data.get(real_ext_name) {\n            Some(_ext_data) => Ok((","sourceCodeStart":385,"sourceCodeEnd":421,"githubUrl":"https://github.com/neondatabase/neon/blob/8f60b04da47ffefe0e52bda2440134b42874eb75/libs/compute_api/src/spec.rs#L385-L421","documentation":"Thrown by RemoteExtSpec::get_ext() in neon's compute_api when is_library is true and the library name (after stripping any .so / .so.N suffix with regex \\.so.*) is not a key in the RemoteExtSpec.library_index map. library_index maps raw shared-library names to the extension that provides them, and it is built from the remote extension archive listing sent by the control plane. A miss means the compute's extension spec simply does not know which extension ships that library.","triggerScenarios":"get_ext(\"pg_stat_statements.so\", true, ...) or get_ext(\"vector.so.3\", true, ...) when \"pg_stat_statements\" / \"vector\" is not a key in library_index; also any shared_preload_libraries / LOAD of a library that has no corresponding entry in the spec's library index.","commonSituations":"A shared_preload_libraries entry for a library whose extension is not present in the tenant's available extension set; custom extensions uploaded to the control plane without the library mapping; version skew between the compute image and the remote extension index after an upgrade; typos in the library name in the compute spec.","solutions":["Check the exact library name after .so-suffix stripping against the library_index keys of the RemoteExtSpec (dump the spec JSON) to see what is actually available","Remove the library from shared_preload_libraries (or the LOAD statement) in the compute spec, or install/upload the extension so the control plane adds it to library_index","If the extension exists but is missing from custom_extensions, register it as a custom extension so its libraries get indexed","After fixing the extension set, retry the operation that built the compute spec"],"exampleFix":"# before (spec)\nshared_preload_libraries = 'pg_stat_statements, timescaledb'\n# but library_index has no \"timescaledb\" key\n\n# after\nshared_preload_libraries = 'pg_stat_statements'  # or add timescaledb to available extensions","handlingStrategy":"validation","validationCode":"// Check the library resolves before calling get_ext:\nfn library_resolves(spec: &RemoteExtSpec, lib: &str) -> bool {\n    let raw = Regex::new(r\"\\.so.*\").unwrap().replace(lib, \"\").to_string();\n    spec.library_index.contains_key(&raw)\n}","typeGuard":null,"tryCatchPattern":"// Inspect the error string to separate 'unknown library' from allow-list/data errors:\nmatch spec.get_ext(lib, true, tag, ver) {\n    Ok((name, path)) => { /* download */ }\n    Err(e) if e.to_string().starts_with(\"library\") => {\n        // skip or report the unknown shared library, keep starting the compute\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Validate every shared_preload_libraries entry against spec.library_index before compute start","When adding custom extensions, include their shared libraries in the library index","Fail fast in CI on specs that reference libraries missing from the index"],"tags":["neon","compute-api","extensions","shared-library","postgres"],"backgroundTag":"dependency-not-found","analyzedSha":"8f60b04da47ffefe0e52bda2440134b42874eb75","analyzedAt":"2026-08-16T23:39:28.135Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}