withastro/astro

"secret server variables" are validated at build time violating the docs

Closed this issue · 9 comments

Astro Info

Astro                    v5.0.3
Node                     v18.20.3
System                   Linux (x64)
Package Manager          unknown
Output                   static
Adapter                  none
Integrations             none

If this issue only occurs in one browser, which browser is a problem?

Chrome

Describe the Bug

As described in the documentation, only public environment variables are validated during build time. However, when I set an environment variable as a server secret, it is still being validated at build time, resulting in an error.

While I can temporarily resolve this by assigning a default value to the variable, this workaround is not mentioned in the documentation, and it does not seem to align with the intended behavior outlined.

Screenshot 2024-12-09 at 15 24 39

astro.config.mjs

// @ts-check
import { defineConfig, envField } from 'astro/config';

// https://astro.build/config
export default defineConfig({
  env: {
    schema: {
      PORTAL_HOST: envField.string({
        context: 'server',
        access: 'secret',
      }),
    },
  },
});

Error info

npm run build

> @example/basics@0.0.1 build
> astro build

15:30:36 [content] Syncing content
15:30:36 [content] Synced content
15:30:36 [types] Generated 125ms
15:30:36 [build] output: "static"
15:30:36 [build] directory: /home/projects/withastro-astro-noe3rg6f/dist/
15:30:36 [build] Collecting build info...
15:30:36 [build] ✓ Completed in 163ms.
15:30:36 [build] Building static entrypoints...
15:30:37 [vite] ✓ built in 827ms
15:30:37 [build] ✓ Completed in 1.09s.

 generating static routes 
[EnvInvalidVariables] The following environment variables defined in `env.schema` are invalid:

- PORTAL_HOST is missing

  Error reference:
    https://docs.astro.build/en/reference/errors/env-invalid-variables/
  Location:
    /home/projects/withastro-astro-noe3rg6f/node_modules/astro/dist/core/build/index.js:198:7
  Stack trace:
    at async AstroBuilder.run (file:///home/projects/withastro-astro-noe3rg6f/node_modules/astro/dist/core/build/index.js:198:7)
    at async build (file:///home/projects/withastro-astro-noe3rg6f/node_modules/astro/dist/cli/build/index.js:44:3)

What's the expected result?

The secret server variables should not be validated at build time.

Link to Minimal Reproducible Example

https://stackblitz.com/edit/withastro-astro-noe3rg6f?file=src%2Fpages%2Findex.astro

Participation

  • I am willing to submit a pull request for this issue.

It is not validated at build time here. Indeed, you call a secret in a prerendered page and as you can see, the error is thrown while rendering static pages (generating static routes). In order to build static pages that use a secret, you need this secret to be set while building. Hope that helps!

@florian-lefebvre
I am having the same issue, and I still believe its a bug.

Our build started failing once we upgraded from 5.0.0-beta.8 to 5.0.2 due to environment variables being accessed at build time, although no other code changes occured. Something internal to Astro changed that brought up the issue.

We have output: "server" configured, so none of our pages should be prerendered.

In fact, I deleted the whole pages folder and ran astro build and still get errors about missing environment variables.
Then I deleted each file that imports a particular env variable, and still get the error.

export default defineConfig({
  output: "server",
  adapter: node({ mode: "standalone" }),
  prefetch: true,
  security: { checkOrigin: true },
  env: {
    schema: {
      KEYCLOAK_CLIENT_SECRET: envField.string({
        context: "server",
        access: "secret",
      })
    }
  }
})

Astro build:

13:26:09 [content] Syncing content
13:26:09 [content] Synced content
13:26:09 [types] Generated 53ms
13:26:09 [build] output: "server"
13:26:09 [build] directory: REDACTED\dist\
13:26:09 [build] adapter: @astrojs/node
13:26:09 [build] Collecting build info...
13:26:09 [build] ✓ Completed in 106ms.
13:26:09 [build] Building server entrypoints...
13:26:10 [vite] ✓ built in 1.52s
13:26:10 [build] ✓ Completed in 1.56s.

 building client (vite) 
13:26:10 [vite] ✓ 3 modules transformed.
13:26:10 [vite] dist/client/_astro/page.V2R8AmkL.js  2.16 kB │ gzip: 0.97 kB
13:26:10 [vite] ✓ built in 58ms
[EnvInvalidVariables] The following environment variables defined in `env.schema` are invalid:

- KEYCLOAK_CLIENT_SECRET is missing

@pothos-dev can you provide a minimal reproduction through https://astro.new/repro?

I managed to localize the issue:

Since 5.0.0, astro build imports the middleware entry point at build time in BuildPipeline.retrieveManifest.
This in turn imports a server-only module that accesses an environment variable (not defined at build time) in the root scope, and therefore crashes the build.

Previously, the middleware was merely compiled (?), not evaluated by astro build.

A workaround might be to not access environment variables in the root scope of a module that is imported in middleware, but wrap the access in a function. But this requires us to rewrite a lot of code (our db is just a top-level export created on import), and is an unexpected behaviour change coming from the Astro 5 beta to release.

As an example, run astro build in this Stackblitz: https://stackblitz.com/edit/github-zmefz6re

@ematipico I'll need your help on this one

Previously, the middleware was merely compiled (?), not evaluated by astro build.

This was never the case. The middleware has always been loaded during the build, if you have pre-rendered pages. This hasn't changed, AFAIK.

Previously, the middleware was merely compiled (?), not evaluated by astro build.

This was never the case. The middleware has always been loaded during the build, if you have pre-rendered pages. This hasn't changed, AFAIK.

Okay, but it wasn't the case if you had only server-rendered pages. Now it is the case even if you have only server-rendered pages, or no pages at all.

@pothos-dev can you try this preview release and tell us if that fixes your issue? astro@experimental--middleware-fix

@ematipico I can confirm that this branch fixes the build-time issues we've seen!