await is only valid in async functions and the top level bodies of modules
Unanswered
Blue Picardy Spaniel posted this in #help-forum
Blue Picardy SpanielOP
import { createServerActionProcedure } from "zsa";
import { getUser } from "@/lib/auth";
export const authenticatedAction = createServerActionProcedure().handler(
async () => {
const user = await getUser();
if(!user) return null;
return { user };
}
);
"use server";
import { z } from "zod";
import { authenticatedAction } from "@/utils/server-only";
import { GuildCollection } from "@/lib/db";
import { ratelimitByKey } from "@/lib/ratelimiter";
export const saveModuleToggleAction = authenticatedAction
.createServerAction()
.input(
z.object({
guildId: z.string(),
module: z.string(),
enabled: z.boolean()
})
)
.handler(async ({ input, ctx: { user } }) => {
const canAccess = await ratelimitByKey(`settings-${user._id}`, 10, 10);
if(!canAccess) return { error: "You are being rate limited." };
console.log("Success");
});
"use client";
import { Button } from "@mantine/core";
import { useServerAction } from "zsa-react";
import { saveModuleToggleAction } from "@/app/dashboard/[guild_id]/actions";
export default function ModuleWrapper() {
const { execute: saveModuleToggle } = useServerAction(saveModuleToggleAction);
function enableModule() {
saveModuleToggle({
guildId: guild.id,
module: moduleName,
enabled: true
});
}
return (
<Button onClick={enableModule}>
);
}
GET /dashboard/1160247290225754204/server-backups 200 in 232ms
⨯ SyntaxError: await is only valid in async functions and the top level bodies of modules
at (action-browser)/./src/lib/db.ts (C:\Users\ethan\Desktop\Projects\watchdog\website\.next\server\app\dashboard\[guild_id]\server-backups\page.js:1099:1)
at __webpack_require__ (C:\Users\ethan\Desktop\Projects\watchdog\website\.next\server\webpack-runtime.js:33:43)
at eval (./src/lib/api/discord.ts:9:65)
at (action-browser)/./src/lib/api/discord.ts (C:\Users\ethan\Desktop\Projects\watchdog\website\.next\server\app\dashboard\[guild_id]\server-backups\page.js:989:1)
at __webpack_require__ (C:\Users\ethan\Desktop\Projects\watchdog\website\.next\server\webpack-runtime.js:33:43)
at eval (./src/utils/server-only.ts:8:74)
at (action-browser)/./src/utils/server-only.ts (C:\Users\ethan\Desktop\Projects\watchdog\website\.next\server\app\dashboard\[guild_id]\server-backups\page.js:1317:1)
at __webpack_require__ (C:\Users\ethan\Desktop\Projects\watchdog\website\.next\server\webpack-runtime.js:33:43)
at eval (./src/app/dashboard/[guild_id]/actions.ts:10:76)
at (action-browser)/./src/app/dashboard/[guild_id]/actions.ts (C:\Users\ethan\Desktop\Projects\watchdog\website\.next\server\app\dashboard\[guild_id]\server-backups\page.js:534:1)
at Function.__webpack_require__ (C:\Users\ethan\Desktop\Projects\watchdog\website\.next\server\webpack-runtime.js:33:43)
digest: "2299097498"
POST /dashboard/1160247290225754204/server-backups 500 in 41ms
Any ideas? When I remove the part where I invoke
saveModuleToggle()
, the error no longer occurs.66 Replies
⨯ SyntaxError: await is only valid in async functions and the top level bodies of modules
at (action-browser)/./src/lib/db.ts
where is your db.ts?
at (action-browser)/./src/lib/db.ts
where is your db.ts?
can u share your code
this sounds like some weird typescript config error
Blue Picardy SpanielOP
it's unrelated but sure
import type { Collection } from "mongodb";
import { MongoClient } from "mongodb";
import { env } from "@/env";
import type { DbGuild, DbSession, DbUser } from "@/types/db";
// Connect
const client = new MongoClient(env.DATABASE_URL);
await client.connect();
// Schemas
const db = client.db();
export const UserCollection = db.collection("users") as Collection<DbUser>;
export const SessionCollection = db.collection("sessions") as Collection<DbSession>;
export const GuildCollection = db.collection("guilds") as Collection<DbGuild>;
it is related
Blue Picardy SpanielOP
alright
await client.connect();
wrap that function in a async function
and trigger on MongoClient callback
Blue Picardy SpanielOP
hm okay
import type { Collection } from "mongodb";
import { MongoClient } from "mongodb";
import { env } from "@/env";
import type { DbGuild, DbSession, DbUser } from "@/types/db";
// Connect
const client = new MongoClient(env.DATABASE_URL);
(async () => {
client.connect().then(() => console.log("connected"));
})();
// Schemas
const db = client.db();
export const UserCollection = db.collection("users") as Collection<DbUser>;
export const SessionCollection = db.collection("sessions") as Collection<DbSession>;
export const GuildCollection = db.collection("guilds") as Collection<DbGuild>;
after doing that im now getting an error in another file..
⨯ src\lib\cache.ts (4:16) @ eval
⨯ ReferenceError: await is not defined
import { createClient } from "redis";
import { env } from "@/env";
const client = await createClient({
socket: {
port: 6379,
host: env.SERVER_IP
},
password: env.REDIS_PASSWORD
}).connect();
export default client;
but what i dont understand is both of these were fine earlier. literally removing
saveModuleToggle({
guildId: guild.id,
module: moduleName,
enabled: true
});
fixes everythingwhat?
the function?
Blue Picardy SpanielOP
yeah
Blue Picardy SpanielOP
no it communicates with my cache
u typically want to save your db instance and return that with a singleton
so u have a getter
for your db
Blue Picardy SpanielOP
i removed the db logic for debugging
i wanted a minimal repro
if i remove the cache stuff in the function and just add a console.log, i still get the error
what error and where
Blue Picardy SpanielOP
export const saveModuleToggleAction = authenticatedAction
.createServerAction()
.input(
z.object({
guildId: z.string(),
module: z.string(),
enabled: z.boolean()
})
)
.handler(async ({ input, ctx: { user } }) => {
const canAccess = await ratelimitByKey(`settings-${user._id}`, 10, 10);
if(!canAccess) return { error: "You are being rate limited." };
console.log("Success");
});
if i remove
await ratelimitByKey
which communicates with the cache (where my [2nd error](https://nextjs-forum.com/post/1282090770345496586#message-1282093447297106052) is coming from), i still get the same [original error](https://nextjs-forum.com/post/1282090770345496586#message-1282090770345496586)but if i don't invoke saveModuleToggleAction() then i simply don't get the error anymore
im just trying to use server actions via a library called zsa which im new to, so im guessing im doing something wrong with that library, especially since if i dont invoke the function then the errors dont appear anymore
send your error log
the current error that u face
Blue Picardy SpanielOP
POST /dashboard/1160247290225754204/server-backups 500 in 149ms
⨯ src\lib\cache.ts (4:16) @ eval
⨯ ReferenceError: await is not defined
at eval (./src/lib/cache.ts:10:16)
at (action-browser)/./src/lib/cache.ts (C:\Users\ethan\Desktop\Projects\watchdog\website\.next\server\app\dashboard\[guild_id]\server-backups\page.js:1077:1)
at __webpack_require__ (C:\Users\ethan\Desktop\Projects\watchdog\website\.next\server\webpack-runtime.js:33:43)
at eval (./src/lib/api/discord.ts:10:68)
at (action-browser)/./src/lib/api/discord.ts (C:\Users\ethan\Desktop\Projects\watchdog\website\.next\server\app\dashboard\[guild_id]\server-backups\page.js:989:1)
at __webpack_require__ (C:\Users\ethan\Desktop\Projects\watchdog\website\.next\server\webpack-runtime.js:33:43)
at eval (./src/utils/server-only.ts:8:74)
at (action-browser)/./src/utils/server-only.ts (C:\Users\ethan\Desktop\Projects\watchdog\website\.next\server\app\dashboard\[guild_id]\server-backups\page.js:1317:1)
at __webpack_require__ (C:\Users\ethan\Desktop\Projects\watchdog\website\.next\server\webpack-runtime.js:33:43)
at eval (./src/app/dashboard/[guild_id]/actions.ts:10:76)
at (action-browser)/./src/app/dashboard/[guild_id]/actions.ts (C:\Users\ethan\Desktop\Projects\watchdog\website\.next\server\app\dashboard\[guild_id]\server-backups\page.js:534:1)
at Function.__webpack_require__ (C:\Users\ethan\Desktop\Projects\watchdog\website\.next\server\webpack-runtime.js:33:43)
digest: "2769027943"
2 | import { env } from "@/env";
3 |
> 4 | const client = await createClient({
| ^
5 | socket: {
6 | port: 6379,
7 | host: env.SERVER_IP
connected
connected
ah i see
so
try this:
const client = redis.createClient({
socket: {
host: "ip",
port: 6969,
},
password: "your pw",
});
try {
await client.connect();
} catch (error: any) {
console.error(error);
}
Blue Picardy SpanielOP
done
GET /dashboard/1160247290225754204/server-backups 200 in 2518ms
⨯ SyntaxError: await is only valid in async functions and the top level bodies of modules
at (action-browser)/./src/lib/cache.ts (C:\Users\ethan\Desktop\Projects\watchdog\website\.next\server\app\dashboard\[guild_id]\server-backups\page.js:1077:1)
at __webpack_require__ (C:\Users\ethan\Desktop\Projects\watchdog\website\.next\server\webpack-runtime.js:33:43)
at eval (./src/lib/api/discord.ts:10:68)
at (action-browser)/./src/lib/api/discord.ts (C:\Users\ethan\Desktop\Projects\watchdog\website\.next\server\app\dashboard\[guild_id]\server-backups\page.js:989:1)
at __webpack_require__ (C:\Users\ethan\Desktop\Projects\watchdog\website\.next\server\webpack-runtime.js:33:43)
at eval (./src/utils/server-only.ts:8:74)
at (action-browser)/./src/utils/server-only.ts (C:\Users\ethan\Desktop\Projects\watchdog\website\.next\server\app\dashboard\[guild_id]\server-backups\page.js:1317:1)
at __webpack_require__ (C:\Users\ethan\Desktop\Projects\watchdog\website\.next\server\webpack-runtime.js:33:43)
at eval (./src/app/dashboard/[guild_id]/actions.ts:10:76)
at (action-browser)/./src/app/dashboard/[guild_id]/actions.ts (C:\Users\ethan\Desktop\Projects\watchdog\website\.next\server\app\dashboard\[guild_id]\server-backups\page.js:534:1)
at Function.__webpack_require__ (C:\Users\ethan\Desktop\Projects\watchdog\website\.next\server\webpack-runtime.js:33:43)
digest: "1821699749"
POST /dashboard/1160247290225754204/server-backups 500 in 52ms
connected
connected
are you directly using
client
somewhere?wrap your createClient in a seperate function have that return your client
and await that function
Blue Picardy SpanielOP
yes im importing from my cache file
let client;
async function createRedisClient() {
const client = createClient({
socket: {
host: "ip"
port: 6969
},
password: "pw",
});
await client.connect();
return client;
}
export async function getRedisClient() {
if (!client) {
client = await createRedisClient();
}
return client;
}
@Blue Picardy Spaniel
Blue Picardy SpanielOP
if i do
const cachedGuilds = await getRedisClient().get(key);
it returns Property 'get' does not exist on type 'Promise<any>'.
try giving it a type
Blue Picardy SpanielOP
of what
idk u need to check
Blue Picardy SpanielOP
u see it
RedisClientType
Blue Picardy SpanielOP
i genuinely dont think redis or mongodb are the issue.. if i remove my redis implementation and just make it like this:
then i still get [the original error](https://nextjs-forum.com/post/1282090770345496586#message-1282090770345496586). so this is nothing to do with any of that as it all works fine. the issue is something to do with zsa or zsa-react as when i remove the zsa invocation, everything works fine
"use server";
import { z } from "zod";
import { authenticatedAction } from "@/utils/server-only";
export const saveModuleToggleAction = authenticatedAction
.createServerAction()
.input(
z.object({
guildId: z.string(),
module: z.string(),
enabled: z.boolean()
})
)
.handler(async ({ input, ctx: { user } }) => {
console.log("Success");
return { success: true };
});
then i still get [the original error](https://nextjs-forum.com/post/1282090770345496586#message-1282090770345496586). so this is nothing to do with any of that as it all works fine. the issue is something to do with zsa or zsa-react as when i remove the zsa invocation, everything works fine
well
the call stack shows something different
i dont think its lying to you xD
?
u need to set the return type for your getter
dont give the client a type
cause RedisClientType is a promise
and your client cant have that in the initial value
Blue Picardy SpanielOP
@gin yo u were right, sorry for doubting you
still not sure why top level await isnt working when i use server actions tho
Blue Picardy SpanielOP
yea