#Uncaught Error: EnvInvalidVariable while deploying to Cloudflare

54 messages · Page 1 of 1 (latest)

fathom terrace
#

Hey guys, I have some issues with env variables while I try to deploy on Cloudflare pages. I'm trying to use the experimental way of using variables.

What I did:

.dev.vars:

GOOGLE_CLIENT_ID = "some-id"
GOOGLE_CLIENT_SECRET = "some-secret"

I added experimental.env.schema to config:

astro.config.ts

import db from "@astrojs/db";
import tailwind from "@astrojs/tailwind";
import { defineConfig, envField } from "astro/config";
import cloudflare from "@astrojs/cloudflare";

import react from "@astrojs/react";


export default defineConfig({
    integrations: [
        db(),
        tailwind({
            nesting: true,
        }),
        react(),
    ],
    output: "server",
    adapter: cloudflare(),
    experimental: {
        env: {
            schema: {
                GOOGLE_CLIENT_ID: envField.string({
                    context: "server",
                    access: "secret",
                }),
                GOOGLE_CLIENT_SECRET: envField.string({
                    context: "server",
                    access: "secret",
                }),
            },
        },
    },
    vite: {
        optimizeDeps: {
            exclude: ["astro:db"],
        },
    },
});

localy build works, but on cloudflare I'm getting:

Error: Failed to publish your Function. Got error: Uncaught Error: EnvInvalidVariable: The following environment variable does not match the data type and/or properties defined in `experimental.env.schema`: GOOGLE_CLIENT_ID is not of type undefined

In cloudflare I added variables inside Settings > Environment variables tab and I can't figure out why em I getting this error. I even commited .dev.vars file.

Any suggestion what should I read to resolve this?

Thank you!

#

Uncaught Error: EnvInvalidVariable while deploying to Cloudflare

remote orbit
#

We've seen this before, but it shouldbe fixed 🤔

#

You schouldn't need to commit the .dev.vars file

#

I guess it might be a usage issue. Where exactly do you use GOOGLE_ClIENT_ID, in a middleware or astro page, or in a shared file?

rough edge
#

First of all, make sure to update astro and the adapter to ther latest version as i'm constantly pushing fixes to astro:env

#

Then yeah we probably need to see how you actually use this var

fathom terrace
#

I'm using it in combination with Lucia for auth.

import { Lucia } from "lucia";
import { AstroDBAdapter } from "lucia-adapter-astrodb";
import { db, session, user } from "astro:db";
import { Google } from "arctic";
import {
    GOOGLE_CLIENT_ID,
    GOOGLE_CLIENT_SECRET,
    GOOGLE_REDIRECT_URI,
} from "astro:env/server";

const adapter = new AstroDBAdapter(db, session, user);

export const lucia = new Lucia(adapter, {
    sessionCookie: {
        attributes: {
            secure: import.meta.env.PROD,
        },
    },
    getUserAttributes: (attributes) => {
        return {
            picture: attributes.picture,
            name: attributes.name,
            email: attributes.email,
            // googleId: attributes.google_id,
        };
    },
});

declare module "lucia" {
    interface Register {
        Lucia: typeof lucia;
        DatabaseUserAttributes: Omit<typeof user, "id">;
    }
}

export const google = new Google(
    GOOGLE_CLIENT_ID,
    GOOGLE_CLIENT_SECRET,
    GOOGLE_REDIRECT_URI,
);

I tried using it directly as in code and I tried using it with getSecret('GOOGLE_CLIENT_ID' ... and the same issue was appearing.

#

My middleware:

import { lucia } from "./lib/auth";
import { verifyRequestOrigin } from "lucia";
import { defineMiddleware } from "astro:middleware";

export const onRequest = defineMiddleware(async (context, next) => {
    console.log(
        "context.request.COOKIE",
        lucia.sessionCookieName,
        context.cookies.get(lucia.sessionCookieName)?.value,
    );
    // if (context.request.url.startsWith("/api")) {
    //     return next();
    // }

    // if (context.request.method !== "GET") {
    //     const originHeader = context.request.headers.get("Origin");
    //     const hostHeader = context.request.headers.get("Host");
    //     if (
    //         !originHeader ||
    //         !hostHeader ||
    //         !verifyRequestOrigin(originHeader, [hostHeader])
    //     ) {
    //         console.log("Invalid origin", originHeader, hostHeader);
    //         return new Response(null, {
    //             status: 403,
    //         });
    //     }
    // }

    const sessionId = context.cookies.get(lucia.sessionCookieName)?.value ?? null;
    if (!sessionId) {
        context.locals.user = null;
        context.locals.session = null;
        return next();
    }

    const { session, user } = await lucia.validateSession(sessionId);
    if (session?.fresh) {
        const sessionCookie = lucia.createSessionCookie(session.id);
        context.cookies.set(
            sessionCookie.name,
            sessionCookie.value,
            sessionCookie.attributes,
        );
    }
    if (!session) {
        const sessionCookie = lucia.createBlankSessionCookie();
        context.cookies.set(
            sessionCookie.name,
            sessionCookie.value,
            sessionCookie.attributes,
        );
    }
    context.locals.session = session;
    context.locals.user = user;

    // console.log("context.locals", context.locals);
    console.log("Request URL", context.request.url);

    return next();
});
remote orbit
#

It looks like you are using the env var outside of a request scope. I don't have an real-world example, @rough edge might have one. But I guess you might want to wrap it inside a function like so.

export const google = () => { return  new Google(
    GOOGLE_CLIENT_ID,
    GOOGLE_CLIENT_SECRET,
    GOOGLE_REDIRECT_URI,
)};

And then call it from inside your middleware with google()

#

It's on my todo list to document this logic inside the adapters docs

fathom terrace
#

@remote orbit thank you for your anser but it didn't work, I'm getting the same error message while deploying to CF

but I have an update too, the only way the deloy works is if I change access: "public" but if I understood correctly the ID and SECRET should be access: "secret" is that corret?

rough edge
#

if you manage to make a minimal reproduction that would be ideal 🙏

#

but yeah in your case you can't export google as const as Alex said

fathom terrace
#

Ah finaly 🙂 here is the repo with only the login

https://github.com/ssf01/astro-cf-env

if I try to run deploy from cli bun run deploy I get

 [ERROR] Deployment failed!

  Failed to publish your Function. Got error: Uncaught Error: Cannot create a remote client: missing
  app token.
    at chunks/auth_CWSkSp7h.mjs:8931:11 in createRemoteDatabaseClient
    at chunks/auth_CWSkSp7h.mjs:9168:18

if I only push to main (git repo is connected to CF and when you push to main it will try to auto deploy) I get:

18:12:39.706    ✨ Success! Uploaded 0 files (4 already uploaded) (0.63 sec)
18:12:39.706    
18:12:40.280    ✨ Upload complete!
18:12:42.231    Success: Assets published!
18:12:43.777    Error: Failed to publish your Function. Got error: Uncaught Error: EnvInvalidVariables: The following environment variables defined in `experimental.env.schema` are invalid:

- GOOGLE_CLIENT_SECRET is missing

  at chunks/astro/env-setup_C7zdctQz.mjs:428:10 in createInvalidVariablesError
  at chunks/auth_t5ndYbAh.mjs:9438:8 in _internalGetSecret
  at chunks/auth_t5ndYbAh.mjs:9447:28
#

if you need I can provide google api keys and everything (I created new astro db, google oath login app everhing for this demo)

remote orbit
#

Took a quick look at the code, I think it is used correct now..
But I haven't tested to run it yet.

#

if I try to run deploy from cli bun run deploy I get

This is expected, because you didn't set the APP Token to process.env in the terminal

  • GOOGLE_CLIENT_SECRET is missing

You're getting a different error now, before it was a type error, because you didn't had the wrapping function, now it's another issue, I haven't seen before. But Florian might know why that is the case.

fathom terrace
#

Thanks I will check the process.env in terminal

fathom terrace
fathom terrace
#

Oh and thank you for the help!

remote orbit
#

That sounds not right though. Not sure if that is a bug

rough edge
#

will check soon

rough edge
#

I'm going to create minimal reproduction to try reproduce it and see what i can do

#

thanks again for the repo it's super helpful

fathom terrace
#

Got it, feel free to clone/fork the repo if needed I hope that I didn't do something wrong and created confution 🙂

rough edge
#

not at all it's great! I'll deploy to cloudflare this afternoon and try get the same as you

rough edge
#

Alright so @remote orbit I think I need your cloudflare knowledge

#

When trying to build on cloudflare with FOO set in env vars:

  • build is working fine
  • "Deploying to Cloudflare's global network" is erroring with FOO is missing
#

do you know what happens during this step?

#

This error is independent of validateSecrets

#

If that helps validateSecrets check vars during build. It works for cloudflare during the build step so i know vars are made available at that point. That's why I'm puzzled by the error occuring during the deploy phase, even without validateSecrets because I would assume vars are also available

#
  • i have no idea why _internalGetSecret is called here
remote orbit
rough edge
#

hah okay i may know what's going on

#

So basically, if FOO is imported from astro:env/server inside a middleware, or if it's imported in a file used in a middleware it will fail

#

however, a dynamic import inside the middleware works

#

this does not look right to me

remote orbit
rough edge
#

ty

#

but i think it's more an issue about how i implemented it, i'm trying to wrap my head around what is executed in what order

remote orbit
#

Not necessarly.. I think it's just missing the request context.. and the middleware is called in the fetch handler, even if no request is sent

fathom terrace
rough edge
#

indeed it's only related to secrets

#

we're working on it! forgot to keep you updated

fathom terrace
#

oh don't worry I will check now and then this post 😉

rough edge
#

i don't think we'll have an immediate fix as I'm OOO next week but we're testing stuff and definitely want this to be fixed

fathom terrace
#

I'm not in hurry, I moved the code that made an issue for middleware so I'm not blocked, but thanks!

rough edge
#

if that can help you

  • if a middleware imports a secret OR reference a file that imports a secret, it will fail
  • if you want to use a secret inside the middeware, use a dynamic import instead
#
defineMiddleware(async () => {
  const { FOO } = await import("astro:env/server")
})