{"record":{"id":"248ab1cdd2aea221","repo":"neondatabase/neon","slug":"extension-is-not-found","errorCode":null,"errorMessage":"extension {} is not found","messagePattern":"extension (.+?) is not found","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"libs/compute_api/src/spec.rs","lineNumber":417,"sourceCode":"\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((\n                real_ext_name.to_string(),\n                Self::build_remote_path(build_tag, pg_major_version, real_ext_name)?,\n            )),\n            None => Err(anyhow::anyhow!(\n                \"real_ext_name {} is not found\",\n                real_ext_name\n            )),\n        }\n    }\n\n    /// Get the architecture-specific portion of the remote extension path. We\n    /// use the Go naming convention due to Kubernetes.\n    fn get_arch() -> &'static str {\n        match std::env::consts::ARCH {","sourceCodeStart":399,"sourceCodeEnd":435,"githubUrl":"https://github.com/neondatabase/neon/blob/8f60b04da47ffefe0e52bda2440134b42874eb75/libs/compute_api/src/spec.rs#L399-L435","documentation":"Thrown by RemoteExtSpec::get_ext() in neon's compute_api when the (possibly library-mapped) extension name is not present in either RemoteExtSpec.public_extensions or RemoteExtSpec.custom_extensions. These two lists are the allow-list of extensions this compute is permitted to use, so this error is an authorization/availability check, not a filesystem lookup: the extension is denied because it was never granted to this compute.","triggerScenarios":"get_ext(\"pgcrypto\", false, ...) when pgcrypto is in neither the public nor the custom extension list of the spec; CREATE EXTENSION or a shared library mapped to an extension that is not allow-listed for the tenant/project.","commonSituations":"Tenant requesting an extension that is not in the platform's public extension set and was never uploaded as a custom extension; custom extension uploaded to a different project than the one running the compute; spec built from a stale extension availability list; typos in the extension name in the compute spec.","solutions":["Compare the requested extension name against public_extensions and custom_extensions in the RemoteExtSpec to confirm it is not allow-listed","Upload the extension as a custom extension for this project (or request it be made public) so it lands in the allow-list","Remove the CREATE EXTENSION / preload reference from the compute spec","Check for name typos and version-suffixed names (the comparison is exact string equality)"],"exampleFix":"-- before\nCREATE EXTENSION pgcrypto;  -- not in public_extensions or custom_extensions\n\n-- after\n-- pick an allow-listed extension, e.g. from public_extensions:\nCREATE EXTENSION pg_stat_statements;","handlingStrategy":"validation","validationCode":"// Allow-list check mirroring get_ext's gate:\nfn extension_allowed(spec: &RemoteExtSpec, name: &str) -> bool {\n    let listed = |opt: &Option<Vec<String>>| {\n        opt.as_ref().is_some_and(|v| v.iter().any(|e| e == name))\n    };\n    listed(&spec.public_extensions) || listed(&spec.custom_extensions)\n}","typeGuard":null,"tryCatchPattern":"// Surface a clear 'extension not available for this tenant' message:\nmatch spec.get_ext(name, false, tag, ver) {\n    Ok(res) => res,\n    Err(e) if e.to_string().starts_with(\"extension \") => {\n        return Err(anyhow!(\"extension {name} is not enabled for this project; enable it via the control plane\"));\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Compare requested extensions against the tenant's available-extensions list before generating the spec","Exact-match names (no version suffixes, correct case) when configuring extensions","Automate the allow-list: derive requested extensions from CREATE EXTENSION audits rather than hand-editing"],"tags":["neon","compute-api","extensions","allow-list","postgres"],"backgroundTag":"dependency-not-authorized","analyzedSha":"8f60b04da47ffefe0e52bda2440134b42874eb75","analyzedAt":"2026-08-16T23:39:28.135Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}