withastro / astro

The web framework for content-driven websites. ⭐️ Star to support our work!
https://astro.build
Other
45.58k stars 2.39k forks source link

Astro DB on Cloudflare: Build fails with "Cannot create a remote client: missing app token" error. #10872

Open pMay2021 opened 4 months ago

pMay2021 commented 4 months ago

Astro Info

Astro                    v4.6.4
Node                     v21.7.3
System                   macOS (arm64)
Package Manager          npm
Output                   server
Adapter                  @astrojs/cloudflare
Integrations             @astrojs/tailwind
                         @astrojs/mdx
                         astro:db
                         @astrojs/db/file-url

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

No response

Describe the Bug

My Cloudflare account deploys automatically on GitHub checkin.

Astro DB works fine local and with --remote (though I've been seeing some ENETUNREACH today but let's park that).

Deployment on Cloudflare fails with the following error:

Success: Assets published!
15:21:40.397    Error: Failed to publish your Function. Got error: Uncaught Error: Cannot create a remote client: missing app token.
  at chunks/pages/404_MemiTqFJ.mjs:18015:11 in createRemoteDatabaseClient
  at chunks/pages/404_MemiTqFJ.mjs:18234:18

ASTRO_STUDIO_APP_TOKEN = value, is set on Cloudflare settings.

My configuration is this:

export default defineConfig({
  integrations: [tailwind(), mdx(), db()],
  output: "server",
  adapter: cloudflare()
});

Not sure what else to do.

What's the expected result?

Build to complete and deploy.

Link to Minimal Reproducible Example

It's on my CF deployment.

Participation

matthewp commented 4 months ago

We had some downtime earlier today. Can you confirm that you're still experiencing this?

pMay2021 commented 4 months ago

@matthewp still seeing both the errors.

  1. On my local dev machine, I keep facing the following intermittently:
18:17:01 [ERROR] [Astro DB Error] request to https://gbaimk52fwt9fulhykeljirqxnif-astro.turso.io/v2/pipeline failed, reason: connect ENETUNREACH 2a09:8280:1::6:d39d:443
  1. And when I check in code, the same app token error appears again.

18:19:35.576    Success: Assets published!
18:19:37.675    Error: Failed to publish your Function. Got error: Uncaught Error: Cannot create a remote client: missing app token.
  at chunks/pages/404_MemiTqFJ.mjs:18015:11 in createRemoteDatabaseClient
  at chunks/pages/404_MemiTqFJ.mjs:18234:18
  1. npm run build does not throw any error for me.
ematipico commented 4 months ago

@pMay2021 are you providing the environment variable ASTRO_STUDIO_APP_TOKEN? You should provide either via CI or via CLI

matthewp commented 4 months ago

Locally they would not need the token, it gets retrieved as long as they are logged in. @pMay2021 Can you try logging in again locally? I doubt that's the problem but would help to isolate.

pMay2021 commented 4 months ago

Hi @matthewp what do you mean "login locally"? There's no issue on my local machine. But unfortunately this morning I'm hitting the request to https://gbaimk52fwt9fulhykeljirqxnif-astro.turso.io/v2/pipeline failed, reason: connect ENETUNREACH 2a09:8280:1::6:d39d:443 repeatedly on --remote. I think all three issues are linked to the DB implementation

  1. The ENETUNREACH that occurs frequently (not always; because when I refresh my pages it goes through sometimes and sometimes not)
  2. The failure to do a --force-reset
  3. The failure on Cloudflare build

Stackblitz reproduction

I'm unable to reproduce on Stackblitz. Astro DB doesn't install. I get an error saying

Command failed with exit code 1: npm install @astrojs/db@^0.10.6
npm ERR! code ERR_INVALID_PROTOCOL
npm ERR! Protocol "https:" not supported. Expected "http:"

and when I tried to install manually, I get:

vite] Error when evaluating SSR module /home/projects/github-wdwm38/astro.config.mjs: failed to import "@astrojs/db"
|- Error: Cannot find module '@astrojs/db' imported from '/home/projects/github-wdwm38/astro.config.mjs'

here's the link to a very basic project:

https://stackblitz.com/edit/github-wdwm38?file=astro.config.mjs (it won't built and fails with an error)

I have a question - how do I make the remote database connection work from Stackblitz? I've created a temp token on Studio, do I give it to you to paste it in a .env?

(PS - I apologize if I'm missing something basic. I'm new to a lot of this--but I love Astro though!).

alirexa commented 4 months ago

I have the same problem as @pMay2021, not any problems locally but when trying to deploy, I get this error at the last step:

Error: Failed to publish your Function. Got error: Uncaught Error: Cannot create a remote client: missing app token. at chunks/pages/index_QU-HpiYl.mjs:8513:11 in createRemoteDatabaseClient at chunks/pages/index_QU-HpiYl.mjs:8729:18

I have to point out, I don't have the problem in a previews commit which connects to the DB but no Insert to the DB. The latest commit does DB Insert too.

matthewp commented 4 months ago

@alirexa are you also using Cloudflare?

ematipico commented 4 months ago

@alirexa are you also using Cloudflare?

They do, looking at their astro info output

matthewp commented 4 months ago

@alirexa Did you set the ASTRO_STUDIO_APP_TOKEN environment variable? You can do it in the Settings -> Variables page.

Screen Shot 2024-05-17 at 10 04 05 AM
aurelius-coffee commented 3 months ago

I'm experiencing the same issue. After playing around with this for a little while I found the issue in my case is using db in middleware.ts. Without using it everything works fine. API routes work, form submissions in Astro pages work, I haven't tried actions.

Not sure if I should comment here, or create a new issue, so I'll start here.

Astro Info

Astro v4.9.2 Node v20.13.1 System Linux (x64) Package Manager pnpm Output server Adapter @astrojs/cloudflare Integrations @astrojs/mdx @astrojs/sitemap astro:db @astrojs/db/file-url

Link to reproducible build

https://github.com/aurelius-coffee/my-astro-app/tree/main

I tried stackblitz, but couldn't log into astro studio there.

image

matthewp commented 3 months ago

Very interesting, we'll check that out.

aurelius-coffee commented 3 months ago

If this was turso I think we could create the db var inside the middleware using context.locals.runtime no problem, something like this:

import { defineMiddleware } from "astro:middleware";
import { drizzle } from "drizzle-orm/libsql";
import { createClient } from "@libsql/client/web";

import { comments } from '../lib/schema'

// `context` and `next` are automatically typed
export const onRequest = defineMiddleware(async (context, next) => {
    const turso = createClient({
        url: context.locals.runtime.env.TURSO_DATABASE_URL!,
        authToken: context.locals.runtime.env.TURSO_AUTH_TOKEN,
      });

    const db = drizzle(turso);
    const result = await db.select().from(comments).all();
    console.log('result is', result)
    return next()
});
pMay2021 commented 3 months ago

new edit: I can now confirm that if I remove the dependency on Astro DB from middleware, Cloudflare builds and works.

Ok, I'm back after a while. I gave up trying to get it running on CF and focused on getting my features done on the local env, and everything works fine, as in my local instance connects perfectly to the remote Astro DB.

Finally, this morning I tried to deploy on Cloudflare, and it failed in the last step, with the same error as @alirexa

Note: I have configured ASTRO_STUDIO_APP_TOKEN on CF.

Error: Failed to publish your Function. Got error: Uncaught Error: Cannot create a remote client: missing app token.
  at chunks/pages/__ByV4bDDm.mjs:8387:11 in createRemoteDatabaseClient
  at chunks/pages/__ByV4bDDm.mjs:8603:18

Usage of db in middleware

While I don't import "astro:db" in my middleware, I do call a library function that imports "astro:db".

I cannot easily remove the db dependency without breaking a lot of pages.

I can now confirm that if I remove the dependency on Astro DB from middleware, Cloudflare builds and works.

An oddity I noticed

I did notice an oddity on Astro Studio though, not that it matters, but here's what I saw.

For example, when I generate a token, I see something like this on the screen:

550044079a64f3a327c8b1641fe60c4czb5c410f:twbsvvepb2mc283demddk6ieag0u (this won't work, don't worry)

but if I use the copy to clipboard, it actually gives me

550044079a64f3a327c8b1641fe60c4czb5c410f:twbsvvepb2mc283demddk6ieag0u:twbsvvepb2mc283demddk6ieag0u repeating the last : portion.

not sure if that matters.

Astro info


Astro v4.9.2 Node v21.7.3 System macOS (arm64) Package Manager npm Output server Adapter @astrojs/cloudflare Integrations @astrojs/tailwind @astrojs/mdx astro:db @astrojs/db/file-url

Summary

Hopefully, it's now helpful from two examples that the Cloudflare build fails when there's Astro DB dependency in the middleware and this blocker can be resolved.

pMay2021 commented 3 months ago

Tried the new 0.11.6 db patch build... looks like the fix is not in yet. Hopefully soon... :)

robinbakker commented 2 months ago

Just to let you know; I have exactly the same problem as @pMay2021 and @alirexa... Tried to deploy on Cloudflare Pages and got the missing app token error. I've also a reference/usage of "astro:db" in middleware - as I tried to follow the Lucia authentication tutorials (https://lucia-auth.com/getting-started/astro). When I disable the middleware it builds and works indeed - but then we can't use the authentication 😅

Angrigo commented 1 month ago

found a hacky fix for this, it looks like that the env is not propagated to the runtime env of cloudflare worker:


  vite: {
    optimizeDeps: {
      exclude: ["astro:db"]
    },
    define: {
      "process.env.ASTRO_STUDIO_APP_TOKEN": JSON.stringify("hardcodehereyourappstudiotoken"),
    }
  }
alexanderniebuhr commented 1 month ago

found a hacky fix fot this, it looks like that the env is not propagated to the runtime env of cloudflare worker:

  vite: {
    optimizeDeps: {
      exclude: ["astro:db"]
    },
    define: {
      "process.env.ASTRO_STUDIO_APP_TOKEN": JSON.stringify("hardcodehereyourappstudiotoken"),
    }
  }

That is very dangerous and shouldn't be recommended. We are not able to reproduce this issue, otherwise we would fix it.

To get some more data, for everyone who this is happening for, do you have a middleware and do you have prerendered pages as well as server side rendered pages?

alexanderniebuhr commented 1 month ago

I'm pretty sure I know the issue now, and we are working on a fix.

cc @matthewp this should stay in core for now, maybe we need to move it later to the adapters repo. Internal discussion about this is on Discord in the astro:env maintainers thread.

Angrigo commented 1 month ago

To get some more data, for everyone who this is happening for, do you have a middleware and do you have prerendered pages as well as server side rendered pages?

yes, we have a mix of all rendering methods

alexanderniebuhr commented 1 month ago

I understand that, my goal with that question was to find out for which cases the issue happens. I expect it only happens for usage in middleware and prerendered pages, but not for other cases.

thomas-callahan-collibra commented 1 month ago

I think I may have the same problem -- I just updated my Astro codebase (all packages to latest versions) yesterday after having locked versions of all packages a couple of months ago while we concentrated on finishing a site migration, and now my SSR build is missing all of the environment variables (it's fine in static and local dev modes though). For context, we use SSR mode in deployments from a single branch that's used as a realtime preview for site authors, but the actual site deployment is fully static. So we need to support all 3 modes with one codebase.

The vars are correctly set in CF Pages, and are populated correctly in astro.config.mjs where I import some of them using loadEnv, but they are missing when I try to use them via import.meta.env.

After some trial and error I realized that vars prefixed with PUBLIC_ were working in the SSR build, but the rest were missing, so I ended up having to prefix all of my environment variables with PUBLIC_ to get them to work in SSR builds (none of our vars are used outside of the Astro front matter so while this is not ideal, it should be OK from a security perspective because none of the code is shipped to the browser, at least as a temporary workaround).

Also this works as expected if I run a local SSR server using the Node adapter, it's only in CF Pages when using the CF Pages adapter that this problem appears.

alexanderniebuhr commented 1 month ago

@thomas-callahan-collibra i think this is a different issue. I don't have the link for it now, but you might find some answer if you search old issues. loadEnv and import.meta.env is only correct for specific cases if using the Cloudflare adapter. In general we recommend using locals.runtime.env or astro:env

thomas-callahan-collibra commented 1 month ago

@thomas-callahan-collibra i think this is a different issue. I don't have the link for it now, but you might find some answer if you search old issues. loadEnv and import.meta.env is only correct for specific cases if using the Cloudflare adapter. In general we recommend using locals.runtime.env or astro:env

OK thanks, I'll try those.

onnenon commented 1 week ago

Any update on this? Also experiencing the same issue when using an auth middleware with lucia, AstroDB hosted on Cloudflare.

alexanderniebuhr commented 1 week ago

I think you only hit it when the middleware runs for prerendered pages, some of the known workarounds should work for you in that case. I'm not totally sure how we could improve the default behavior 🤔

onnenon commented 1 week ago

Do you have an example I could look at? I confirmed that everything will build properly if I do the hacky fix and hard code my token as described above. I have the token defined in my Cloudflare environment, but it doesn't seem to be picking it up properly.

onnenon commented 1 week ago

Hopefully I'll figure out how to do this better as I get more familiar with Astro. For now I just updated my GitHub action workflow to mutate a placeholder in my astro.config.mjs.

name: Deploy Pages Site

on: push

env:
  ASTRO_STUDIO_APP_TOKEN: ${{ secrets.ASTRO_STUDIO_APP_TOKEN }}

jobs:
  build:
    name: Build and Deploy to Cloudflare
    environment: cloudflare
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version-file: "package.json"
          cache: "npm"
      - name: Install
        run: npm install
      - name: Update Token Placeholder
        run: sed -i "s/PLACEHOLDER/${ASTRO_STUDIO_APP_TOKEN}/" astro.config.mjs
      - name: Build
        run: npm run build:remote
      - name: Deploy
        uses: cloudflare/wrangler-action@v3
        with:
          apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
          command: pages deploy dist --project-name=<your site> --branch ${{ github.ref_name }}
jonaspm commented 1 week ago

+1