Next.js Discord

Discord Forum

file.json built at build-time not found

Answered
American posted this in #help-forum
Open in Discord
AmericanOP
I have a script that creates a json-object in file.json which is located in the root folder. I can access file.json in my code locally, both with 'next dev' and 'next build && next start'. When I deploy it on vercel I get this error: [Error: ENOENT: no such file or directory, open '/var/task/file.json']
{
errno: -2,
syscall: 'open',
path: '/var/task/file.json',
page: '/home'
}
I run the script that creates file.json before 'next build' at build time on vercel. Could the problem be that the file structure is different on vercel so the path I'm using to access file.json is wrong? Thanks for any help!
Answered by Ray
I think you could do this?
google.auth.getClient({
    credentials: {
      type: "service_account",
      project_id: "my-project",
      private_key_id: "aonuUqnocuh234oqlkr",
      private_key: "super-long-string-qsuOHKRU035Okr",
      client_email: "example@mail.com",
      client_id: "Ouhr13QurlohUk03",
      token_url: "https://oauth2.googleapis.com/token",
    },
  });
View full answer

15 Replies

AmericanOP
I'm using googleapis, like this:
const auth = await google.auth.getClient({
    keyFile: "file.json",
  });

I was trying to do something like this https://dev.to/wilsonparson/how-to-securely-use-google-apis-service-account-credentials-in-a-public-repo-4k65 .
keyFile takes the path, so I'm not sure how to import it or if that is viable in this case. Running it locally works, but not on vercel. Is it possible there's extra configuration required when an "additional" file is built like this on vercel?
AmericanOP
I'm still getting the same "file not found"-error. Looking at the build logs it looks like the script that builds file.json is executed without any problem, but is there a way to double check that the file actually exists on vercel?
AmericanOP
I can't find file.json anywhere. I'm using fs to write the file like this:
fs.writeFileSync(
    "file.json",
    JSON.stringify(credentials, null, 2)
  );

Maybe it should be done differently for vercel?
AmericanOP
Still "no such file". I tried logging process.cwd() to the console in both the script and where I try to use it. In the script it logs cwd: /vercel/path0, but the other page logs cwd: /var/task
AmericanOP
I tried to move the script inside of the page where it's used to ensure that process.cwd() was the same. This worked locally but on vercel I got an error read-only file system. Does this mean that I'm unable to write files myself at build time as well (before next build)?
AmericanOP
I'm trying to use googleapis. The credentials are stored in a credentials.json:
{
  "type": "service_account",
  "project_id": "my-project",
  "private_key_id": "aonuUqnocuh234oqlkr",
  "private_key": "super-long-string-qsuOHKRU035Okr",
  "client_email": "example@mail.com",
  "client_id": "Ouhr13QurlohUk03",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/{project-specific-stuff}.iam.gserviceaccount.com"
}

The above is what googleapis require to be used here:
const auth = await google.auth.getClient({
    scopes: ["https://www.googleapis.com/auth"],
  });

This credentials used above are usually accessed from the .env like this GOOGLE_APPLICATION_CREDENTIALS=./credentials.json
keyFile is used to specify a different path keyFile: "credentials.json", but unecessary if you get the credentials from the .env fil like above.
To avoid exposing API-keys in the json-file I tried to add the data from credentials, one by one to .env, then build a json file from the .env-data at build time, which then is used by googleapis at google.auth.getClient with the keyFile pointing to this json-file I generated.
The same as is done in this article https://dev.to/wilsonparson/how-to-securely-use-google-apis-service-account-credentials-in-a-public-repo-4k65
@American I'm trying to use `googleapis`. The credentials are stored in a `credentials.json`: { "type": "service_account", "project_id": "my-project", "private_key_id": "aonuUqnocuh234oqlkr", "private_key": "super-long-string-qsuOHKRU035Okr", "client_email": "example@mail.com", "client_id": "Ouhr13QurlohUk03", "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/{project-specific-stuff}.iam.gserviceaccount.com" } The above is what `googleapis` require to be used here: const auth = await google.auth.getClient({ scopes: ["https://www.googleapis.com/auth"], }); This credentials used above are usually accessed from the .env like this `GOOGLE_APPLICATION_CREDENTIALS=./credentials.json` keyFile is used to specify a different path `keyFile: "credentials.json"`, but unecessary if you get the credentials from the .env fil like above. To avoid exposing API-keys in the json-file I tried to add the data from credentials, one by one to .env, then build a json file from the .env-data at build time, which then is used by `googleapis` at `google.auth.getClient` with the `keyFile` pointing to this json-file I generated. The same as is done in this article https://dev.to/wilsonparson/how-to-securely-use-google-apis-service-account-credentials-in-a-public-repo-4k65
I think you could do this?
google.auth.getClient({
    credentials: {
      type: "service_account",
      project_id: "my-project",
      private_key_id: "aonuUqnocuh234oqlkr",
      private_key: "super-long-string-qsuOHKRU035Okr",
      client_email: "example@mail.com",
      client_id: "Ouhr13QurlohUk03",
      token_url: "https://oauth2.googleapis.com/token",
    },
  });
Answer
then use env variable for the property
AmericanOP
Now it works. Thank you so much for all your help! 🙂