Astro env var undefined in browser (missing PUBLIC_ prefix) in CI
Astro exposes environment variables through import.meta.env, but only variables prefixed PUBLIC_ reach client-side code; everything else stays server-only for safety. Reading a non-PUBLIC var (or process.env) in the browser yields undefined, which frequently breaks a build check or an end-to-end test in CI.
What this error means
A client-side value is undefined at runtime, or a build/test fails because import.meta.env.API_URL (no PUBLIC_ prefix) is empty in the browser.
TypeError: Cannot read properties of undefined (reading 'toString')
// import.meta.env.API_URL is undefined in client code (no PUBLIC_ prefix)Common causes
A non-PUBLIC var read in the client
Client code reads import.meta.env.SOMETHING without the PUBLIC_ prefix, so Astro does not expose it to the browser and it is undefined.
Using process.env in the browser
Client code reads process.env.X; process does not exist in the browser under Astro, so the value is undefined.
How to fix it
Prefix client-safe vars with PUBLIC_
- Rename variables the client needs to
PUBLIC_.... - Read them with
import.meta.env.PUBLIC_...in client code. - Set the variable in the CI environment so the build embeds it.
// client code
const api = import.meta.env.PUBLIC_API_URL;Keep secrets server-only
Read non-public vars only in server code (.astro frontmatter, endpoints, SSR), never in the client, and never via process.env in the browser.
env:
PUBLIC_API_URL: https://api.example.comHow to prevent it
- Prefix any browser-exposed variable with
PUBLIC_. - Never read
process.envin client code under Astro. - Set
PUBLIC_variables in the CI environment so builds embed them.