Likely causes, most common first
The variable's scope does not include Functions
On Pro and Enterprise plans, a variable can be limited to scopes such as Builds, Functions or Runtime. A variable scoped to Builds is visible to the build but not to the function at runtime.
How to tell: The variable is listed for the Builds scope but not for the Functions scope.
The value was added or changed after the deploy that is running
Each deploy, including Deploy Previews and branch deploys, uses the variable values that were set when it was deployed. Adding a variable in the UI does not change a deploy that already exists.
How to tell: The variable appears in the UI, but the running deploy is older than the change.
The variable lives in netlify.toml
Variables declared in netlify.toml are not available to serverless functions. They can look correct, because the value is in the file and in the build. The CLI's env:list is documented as including netlify.toml values, so it can show the key too.
How to tell: The function logs the key as unset, and the key is declared in netlify.toml with no matching site variable that includes the Functions scope in the UI.
A secret is masked outside Netlify
Secret values are write-only, and code running outside Netlify's hosted systems gets masked versions. Secret values must also be set to explicit deploy contexts and scopes.
How to tell: The value is a masked placeholder instead of your real key, while non-secret variables resolve.