How to access .env variables?
Unanswered
Singapura posted this in #help-forum
SingapuraOP
Hi :).
I'm trying to access my environment variables (sensitive) in a server action with Nextjs v15.1.2 but get "undefined". My env file is located at "/project/.env", and I'm trying to access them at "/project/src/app/lib/actions/some_dir/some_file.ts" I've also included "use server" at the top of "some_file.ts" (unsure if that is correct or not). I'm using "process.env.API_KEY" to access my environment variable. Does anyone know I'm receiving "undefined"?
Thanks!
I'm trying to access my environment variables (sensitive) in a server action with Nextjs v15.1.2 but get "undefined". My env file is located at "/project/.env", and I'm trying to access them at "/project/src/app/lib/actions/some_dir/some_file.ts" I've also included "use server" at the top of "some_file.ts" (unsure if that is correct or not). I'm using "process.env.API_KEY" to access my environment variable. Does anyone know I'm receiving "undefined"?
Thanks!
188 Replies
Blue whiting
Are you trying to access it on the client? Because only NEXT_PUBLIC is available on the client. That said, you shouldn't have an API_KEY public
SingapuraOP
nah I'm trying to use SendGrid to send emails
I'm structuring it so that a server action receives form data, which is used in an email
Asian black bear
Have you restarted the dev server after setting up the .env file?
SingapuraOP
like "npm run dev"?
Asian black bear
Yes.
SingapuraOP
yeah, nothing works after taht 😦
is there some requirement i need in my next.config.ts file?
Asian black bear
Not really. Show a screenshot of your file hierarchy, ensure the file is actually called
.env
without excess whitespaces. Also show us the code of the file you're attempting to access the env var in.Blue whiting
And this definitely isn't accessed in the browser at all? I'm surprised you have to mark it as "use server"
@Blue whiting And this definitely isn't accessed in the browser at all? I'm surprised you have to mark it as "use server"
Asian black bear
"use server"
is not meant to mark server-side components.SingapuraOP
heres my .env
"use server"
import sgMail from "@sendgrid/mail";
export async function sendEmail({
name,
email,
message,
}: {
name: string;
email: string;
message: string;
}) {
const SENDGRID_API_KEY = process.env.SENDGRID_API_KEY;
console.log(SENDGRID_API_KEY);
this is the start of my file
I'm unsure if i need "use server"
Asian black bear
Is
SENDGRID_API_KEY
the exact spelling of the variable in .env
? How are you calling sendEmail
and where?"use server"
is only used to mark server actions and not otherwise.SingapuraOP
sendEmail
is being called in a submit-form
file (headed with "use server", which contains the function submitForm
used in my <ContactForm /> component here: const [message, formAction, isPending] = useActionState(submitForm, {});
so on submit -> submitForm -> await sendEmail(...) -> trying to access env variables
Asian black bear
headed with "use server"Drop that. Only files containing server actions need that directive.
SingapuraOP
in send-email or submit-form?
Asian black bear
submit-form. Additionally share the code of that form file.
SingapuraOP
"use server";
import { z } from "zod";
import { sendEmail } from "./send-email";
import { FormState } from "./types";
const ContactFormSchema = z.object({
name: z.string().trim().min(1, "Please enter a name"),
email: z
.string()
.trim()
.email({ message: "Please enter a valid email" })
.regex(/*some regex expression*/, {
message: "Please enter a valid email",
}),
message: z.string().trim().min(1, { message: "Please enter a message" }),
});
export default async function submitForm(
prevState: FormState,
formData: FormData,
): Promise<FormState> {
const data = Object.fromEntries(formData);
const parsedData = ContactFormSchema.safeParse(data);
if (!parsedData.success) {
const formErrors = parsedData.error.format();
return {
state: "error",
formErrors,
body: {
name: data.name.toString(),
email: data.email.toString(),
message: data.message.toString(),
},
};
}
try {
await sendEmail(parsedData.data);
return {
state: "success",
body: parsedData.data,
};
} catch (error: Error) {
return {
state: "success",
formErrors: error,
body: parsedData.data,
};
}
}
why don't i need "use server" in submit-form? isn't it a server action in my client <ContactForm /> component?
Asian black bear
If your intention is to have
submitForm
be a server action then yes, you need the directive. From your initial explanation I was assuming it was a client-side handler.SingapuraOP
ah
yeah i wanted the form validation to be server
Asian black bear
From your code you've shared so far the other file containing
sendEmail
won't need the directly since it is just called from the server-side.Blue whiting
const SENDGRID_API_KEY = process.env.SENDGRID_API_KEY;
process.env.API_KEY
Asian black bear
What I've mentioned so far isn't too relevant to the actual problem though.
For debugging purposes, just try to access the API key inside the
submitForm
function.@Blue whiting `const SENDGRID_API_KEY = process.env.SENDGRID_API_KEY;`
`process.env.API_KEY`
SingapuraOP
ive got the top line in my sendEmail function, and my .env contains SENDGRID_API_KEY=
@Singapura ive got the top line in my sendEmail function, and my .env contains SENDGRID_API_KEY=
Blue whiting
Do you mind sharing the send email function? Whereabouts is it?
Asian black bear
Now for a really random approach to debug this: attempt to name the variable
NEXT_PUBLIC_SENDGRID_API_KEY
and try accessing it.Just to validate whether or not you can access that.
If that doesn't work either it is indicative of next not picking up your .env file at all.
If you are able to access it, it is indicative of the possibility that your functions are bundled client-side and not server-side.
@Asian black bear Now for a really random approach to debug this: attempt to name the variable `NEXT_PUBLIC_SENDGRID_API_KEY` and try accessing it.
SingapuraOP
did this in sendEmail and got undefined
Blue whiting
restart the server with that too
SingapuraOP
this is so cooked 😭
i did
@Blue whiting Do you mind sharing the send email function? Whereabouts is it?
SingapuraOP
in /project/src/app
when i do start the dev server w/ "npm run dev" it gets some environment:
Asian black bear
Then it should work.
If it clearly displays reading the .env file you should be able to use it without the
NEXT_PUBLIC_
prefix and it means you probably haven't restarted the dev server despite our initial question of whether you did that in the first placeSingapuraOP
i been spamming "npm run dev" after ending current session whenever i make change tho 😦
Blue whiting
Can you write NEXT_PUBLIC_BUG=bug and then console log that?
I did have a situation with a weird string in an .env file, so maybe doing something super simple is worth logging
@Blue whiting Can you write NEXT_PUBLIC_BUG=bug and then console log that?
SingapuraOP
ill try
put it in my <ContactForm /> component and logged "undefiend"
ended current sesion w/ "ctrl + c" then started up again w/ "npm run dev" beforehand
Blue whiting
You have an error in submit-form too
@Singapura put it in my <ContactForm /> component and logged "undefiend"
Blue whiting
That contact form is clientside? I'm getting confused
SingapuraOP
contactForm is client side, it uses the "useActionState" hook from react
Blue whiting
Log it where you're getting the api key
do you guys know what is the env configuration in next.config.js for? should i open my own post?
@Blue whiting Log it where you're getting the api key
SingapuraOP
undefined 😦
Blue whiting
Can you share the code for where you're getting the api key?
Or a few lines of it
@chisto do you guys know what is the env configuration in next.config.js for? should i open my own post?
Asian black bear
Open your separate post.
SingapuraOP
"use server"
import sgMail from "@sendgrid/mail";
export async function sendEmail({
name,
email,
message,
}: {
name: string;
email: string;
message: string;
}) {
const SENDGRID_API_KEY = process.env.SENDGRID_API_KEY;
console.log(SENDGRID_API_KEY);
console.log(process.env.NEXT_PUBLIC_BUG)
if (!SENDGRID_API_KEY) {
throw new Error("Unexpected SendGrid API key error");
}
sgMail.setApiKey(SENDGRID_API_KEY);
const msg = {
to: "hostemail@gmail.com",
from: email,
name: name,
subject:
"Sending with SendGrid is Fun and easy to do anywhere, even with Node.js",
text: message,
html: "<strong>and easy to do anywhere, even with Node.js</strong>",
};
sgMail
.send(msg)
.then(() => {
console.log("Email sent");
})
.catch((error) => {
console.error(error);
});
}
most of it is taken directly from sendgrids site
@Singapura most of it is taken directly from sendgrids site
Blue whiting
are you using windows?
SingapuraOP
yup
Blue whiting
it could be that when you stop the server, it hasn't stopped properly
and therefore hasn't reloaded the .env file
SingapuraOP
hmm
Blue whiting
it's a bit of a crap shoot but i'd reboot (you can manually kill tasks but this would give me reassurance as an outsider)
SingapuraOP
ok ill try that
cooked 😭
Blue whiting
didn't work?
SingapuraOP
didn't work
Blue whiting
damn
SingapuraOP
this is unfortunate
Blue whiting
is it erroring? it should error
Unexpected SendGrid API key error
SingapuraOP
yeah
if i move the api key getting logic to the top of the file
instead of inside the functino body
cuz the function body responds to submitForm, which responds to contactform component
this is tragic, maybe revisit later, i been on this for like 2.5 hours now
Blue whiting
assuming you still have the BUG env I would check browser console and server console. I am just tripple checking
because it still feels like there's more going on
SingapuraOP
okok
Blue whiting
unless something is cache'd, not sure if that's even a possibility in this case
SingapuraOP
import sgMail from "@sendgrid/mail";
const SENDGRID_API_KEY = process.env.SENDGRID_API_KEY;
console.log(process.env.NEXT_PUBLIC_BUG)
console.log(SENDGRID_API_KEY);
if (!SENDGRID_API_KEY) {
throw new Error("Unexpected SendGrid API key error");
}
export async function sendEmail({
name,
email,
message,
}: {
name: string;
email: string;
message: string;
}) {
sgMail.setApiKey(SENDGRID_API_KEY);
both undefined
Blue whiting
undefined in the server console?
SingapuraOP
yup
also
Blue whiting
ok
SingapuraOP
typing in "process.env." doesn't give me the auto-fill thing for SENGRID_API_KEY or NEXT_PUBLIC_BUG
like the smart complete intelligence
Blue whiting
is there something above it in the env
that could be breaking it
SingapuraOP
NODE_ENV=development
is above both
is above both
at the top of the file
i might come visit this later
thanks for the help!
Blue whiting
we didn't help apparently lol!
this is odd
SingapuraOP
well
yall tried
I was also having some issues setting up send grid for my app as well
SingapuraOP
no idea why it doesn't work
@Singapura no idea why it doesn't work
Bit of a random suggestion, but create a .env.local at the root of your project and try it with that
Also your
process.env.SENDGRID_API_KEY
should be process.env.NEXT_PUBLIC_SENDGRID_API_KEY
I thinkI might be wrong though
@Tibbs Bit of a random suggestion, but create a .env.local at the root of your project and try it with that
SingapuraOP
I'll try this tn
how come NEXTPUBLIC
doesn't that indicate a key that is exposed client side
I just looked and I don't think it is NEXT_PUBLIC for the send grid api key
SingapuraOP
I think we tried thay
I didn't use it for mine either when I tried it
SingapuraOP
I might create a fresh repo and see if it works in there
But I am not 100% sure why and when it is needed exactly but for example I have firebase integrated with my app and I had to use NEXT_PUBLIC for my firebase env variables
SingapuraOP
maybe there's some under-the-hood issue that is bugging out my current one
It's possible, I've had it happen before
SingapuraOP
we shall see latee
Good luck with it, if I manage to get send grid working myself I will drop the info here
SingapuraOP
bet
I'm not using typescript but I am sure you won't have any issues switching it
SingapuraOP
I think it's just an env thing tho rn
I can't get any env variable to load
Definitely try the .env.local then and no worries
SingapuraOP
ye I'll do that first
SingapuraOP
ok my env works in another test repo
might just have to scrap this one
Probably something cached somewhere causing issues in the repo
@Singapura ok my env works in another test repo
Blue whiting
delete node modules, next folder and pnpm lock file
SingapuraOP
its fixed woo
just something wrong with old repo
Blue whiting
did deleting the node modules and stuff help?
SingapuraOP
i didn't go thru with that
just created a brand new repo
and i had no more issues with env
or sendgrid, got it working too
@Singapura or sendgrid, got it working too
How did you setup sendgrid in your project please?
SingapuraOP
I only needed something simple
it was for an embedded form
basically just used the template that sendgrid provides when setting it up
changed the "from" field to myself, changed the "to" field to myself, and then changed the reply field to the user inputted email
put the key in my .env file
for dev^
for prod I'm gonna use vercel
I can send the code later
not at my computer rn
Ah I see, not sure if I can use that in my case but basically I am developing an app where people can team up and invest together but sending invites to join the team in firestore is being a real PITA
SingapuraOP
damnn
one thing I noticed is that you have to verify all emails you want to send from
which makes things harfer
I got auth working and team creation working good but the invites has me stumped and verify all emails how? the email you send from or each specific email?
SingapuraOP
not entirely sure, but it's commented out next to the "from" field that it has to be a verified email
I guess to prevent people from sending mail from other people's emails
I barely touched sendgrid
just did what I needed
Ohh I see so a email from a domain or something basically
Instead of gmail or yahoo etc
SingapuraOP
that coild be it
maybe some check on client side where users authorize the use of their email or something
but honestly
if you are sending invite emails
is it possible to send all invite emails from your domain as a no-reply
cuz the you don't have to verify the emails
just your own verified sneder right
Yeah I believe so, I'm pretty sure there will be some config settings you can provide for it if I remember correctly
SingapuraOP
mm I see
idk there's a whole lot of security with sendgrid and twilio
The thing with the verified stuff is that when you use your own gmail account it can be seen as spam when you use it a lot so if you use a domain authenticated sender identity it can be more reputable and the same with a single sender verification, which send grid allows you to setup but I am not 100% sure how it works myself
SingapuraOP
ohh spam
For example when you buy a domain you can get an email for that domain
SingapuraOP
shoo
are you deploying on vercel?
I usually do yeah
SingapuraOP
I wonder if they have a verified email domain
cuz free deploy is goated
Vercel don't specifically, but they will tell you to use something like namecheap or godaddy
SingapuraOP
ah gotcha
so much stuff just for an email 😭
If you do get a domain for it remember to setup the domain settings on vercel too, usually a matter of changing the A DNS records or the CNAME
Haven't done any of that in a while lol
But yeah you're right, I question if things are overkill or needed a lot
SingapuraOP
import sgMail from "@sendgrid/mail";
export async function sendEmail({
name,
email,
message,
}: {
name: string;
email: string;
message: string;
}) {
const SENDGRID_API_KEY = process.env.SENDGRID_API_KEY;
if (!SENDGRID_API_KEY) {
throw new Error("Unexpected SendGrid API key error");
}
sgMail.setApiKey(SENDGRID_API_KEY);
const msg = {
to: "myEmail@email.com",
from: "myEmail@email.com",
name: name,
replyTo: email,
subject: "Message",
text: `New message from user ${name}. Name: ${name}. Email: ${email}. ${message}`,
html: `<h3>New message from user ${name}</h3><p>Name: ${name}</p><p>Email: <a href="mailto:${email}">${email}</a></p><p>${message}</p>`,
};
try {
sgMail.send(msg);
return {
state: "success",
};
} catch {
throw new Error(
"Unexpected email error encountered, please direct your message to myEmail@email.com",
);
}
}
though i wonder if it would be better to put the logic of getting apikey, throwing error, and setting api key outside the function body