Failed to find server action "null". Original error: INvariant: missng 'next-action' header.
Unanswered
Brown bear posted this in #help-forum
Brown bearOP
Having an error like in this github discussion: https://github.com/vercel/next.js/discussions/59105
I tried a few of the solutions people posting but can't seem to fix it.
Here are a few of my files
I tried a few of the solutions people posting but can't seem to fix it.
Here are a few of my files
74 Replies
Brown bearOP
src/app/callack/route.ts
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
import { cookies } from "next/headers";
import { NextRequest, NextResponse } from "next/server";
export async function GET(req: NextRequest) {
const url = new URL(req.url);
//use cookie store and exchange code we got
const code = url.searchParams.get("code");
if (code) {
const cookieStore = cookies();
const supabase = createRouteHandlerClient({
cookies: () => cookieStore,
});
await supabase.auth.exchangeCodeForSession(code);
}
return NextResponse.redirect(url.origin);
}src/app/login/route.ts
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
import { cookies } from "next/headers";
import { NextRequest, NextResponse } from "next/server";
export async function POST(req: NextRequest) {
const url = new URL(req.url);
const cookieStore = cookies();
const formData = await req.formData();
const email = String(formData.get("email"));
const password = String(formData.get("password"));
console.log(email, password);
const supabase = createRouteHandlerClient({
cookies: () => cookieStore,
});
const { data, error } = await supabase.auth.signInWithPassword({
email,
password,
});
if (data) console.log(data);
if (error) console.log(error);
return NextResponse.redirect(url.origin, {
status: 301,
});
}src/app/logout/route.ts
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
import { cookies } from "next/headers";
import { NextRequest, NextResponse } from "next/server";
export async function POST(req: NextRequest) {
const url = new URL(req.url);
const cookieStore = cookies();
const supabase = createRouteHandlerClient({
cookies: () => cookieStore,
});
await supabase.auth.signOut();
return NextResponse.redirect(url.origin, {
status: 301,
});
}src/app/signup/route.ts
import { createRouteHandlerClient } from "@supabase/auth-helpers-nextjs";
import { cookies } from "next/headers";
import { NextRequest, NextResponse } from "next/server";
export async function POST(req: NextRequest) {
const url = new URL(req.url);
const cookieStore = cookies();
const formData = await req.formData();
const email = String(formData.get("email"));
const password = String(formData.get("password"));
const supabase = createRouteHandlerClient({
cookies: () => cookieStore,
});
await supabase.auth.signUp({
email,
password,
options: {
emailRedirectTo: `${url.origin}/auth/callback`,
},
});
return NextResponse.redirect(url.origin, {
status: 301,
});
}src/app/login/page.tsx
export default function Login() {
return (
<form action="/auth/login" method="post">
<label htmlFor="email">Email</label>
<input name="email" className="text-black" />
<label htmlFor="password">Password</label>
<input type="password" name="password" className="text-black" />
<button>Sign In</button>
</form>
);
}src/lib/supabase.ts
import { createClientComponentClient } from "@supabase/auth-helpers-nextjs";
export const supabase = createClientComponentClient();Brown bearOP
src/middleware.ts
import { createMiddlewareClient } from "@supabase/auth-helpers-nextjs";
import { NextResponse, NextRequest } from "next/server";
export async function middleware(req: NextRequest) {
const res = NextResponse.next();
const supabase = createMiddlewareClient({ req, res });
const {
data: { session },
error,
} = await supabase.auth.getSession();
if (!session) {
return NextResponse.rewrite(new URL("/login", req.url));
}
return res;
}
//run middleware on every url except those in this regex natcher
export const config = {
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
};you can't use action props with route handler
Brown bearOP
should it be onsubmit
export default function Login() {
return (
<form onSubmit={async e => {
e.preventDefault()
await fetch("/auth/login", {
method: "POST",
body: new FormData(e.currentTarget)
})
}}>
<label htmlFor="email">Email</label>
<input name="email" className="text-black" />
<label htmlFor="password">Password</label>
<input type="password" name="password" className="text-black" />
<button>Sign In</button>
</form>
);
}try this instead
or turn the route handler to server action
Brown bearOP
@Brown bear Click to see attachment
oh yeah, you will need to use client component
Brown bearOP
when i put use client at the top it doesnt give an error but it just doesnt work at all
like
if you want to use server component then you should turn the route handler to server action
Brown bearOP
when i click submit nothing happens
@Brown bear when i click submit nothing happens
could you show the code again
Brown bearOP
like for these
src/login/page.tsx
src/login/page.tsx
"use client";
export default function Login() {
return (
<form
onSubmit={(e) => {
e.preventDefault();
fetch("/auth/login", {
method: "POST",
body: new FormData(e.currentTarget),
});
}}
method="post"
>
<label htmlFor="email">Email</label>
<input name="email" className="text-black" />
<label htmlFor="password">Password</label>
<input type="password" name="password" className="text-black" />
<button>Sign In</button>
</form>
);
}src/signup/page.tsx
"use client";
export default function Signup() {
return (
<form
onSubmit={(e) => {
e.preventDefault();
fetch("/auth/signup", {
method: "POST",
body: new FormData(e.currentTarget),
});
}}
method="post"
>
<label htmlFor="email">Email</label>
<input name="email" className="text-black" />
<label htmlFor="password">Password</label>
<input type="password" name="password" className="text-black" />
<button>Sign Up</button>
</form>
);
}@Brown bear like for these
src/login/page.tsx
"use client";
export default function Login() {
return (
<form
onSubmit={(e) => {
e.preventDefault();
fetch("/auth/login", {
method: "POST",
body: new FormData(e.currentTarget),
});
}}
method="post"
>
<label htmlFor="email">Email</label>
<input name="email" className="text-black" />
<label htmlFor="password">Password</label>
<input type="password" name="password" className="text-black" />
<button>Sign In</button>
</form>
);
}
export default function Login() {
return (
<form onSubmit={async e => {
e.preventDefault()
await fetch("/auth/login", {
method: "POST",
body: new FormData(e.currentTarget)
})
}}>
<label htmlFor="email">Email</label>
<input name="email" className="text-black" />
<label htmlFor="password">Password</label>
<input type="password" name="password" className="text-black" />
<button>Sign In</button>
</form>
);
}i forgot to use async there
Brown bearOP
should i be using use client
for these files
its better to leave the page component to be a server component
and create the form with client component if you need client side validation
Brown bearOP
after changint to async still get error
add 'use client'
Brown bearOP
after that same issue as before where nothing happens
when i click the button
Brown bearOP
before i wasnt
now after removing method=post
i get this
ok
Brown bearOP
@Brown bear Click to see attachment
is it making a POST request?
Brown bearOP
dont think so
Brown bearOP
same error
you dont have
method: "POST"Brown bearOP
its making the post requests but
nothings happening
not getting redirected
check the log on terminal
Brown bearOP
no log
oh I think you have to add this to the fetch
await fetch("/auth/login", {
method: "POST",
redirect: 'follow'
body: new FormData(e.currentTarget)
})Brown bearOP
same as before
i had
"use client";
export default function Login() {
return (
<form
onSubmit={async (e) => {
e.preventDefault();
await fetch("/auth/login", {
method: "POST",
redirect: "follow",
body: new FormData(e.currentTarget),
});
}}
method="post"
>
<label htmlFor="email">Email</label>
<input name="email" className="text-black" />
<label htmlFor="password">Password</label>
<input type="password" name="password" className="text-black" />
<button>Sign In</button>
</form>
);
}@Brown bear i had
"use client";
export default function Login() {
return (
<form
onSubmit={async (e) => {
e.preventDefault();
await fetch("/auth/login", {
method: "POST",
redirect: "follow",
body: new FormData(e.currentTarget),
});
}}
method="post"
>
<label htmlFor="email">Email</label>
<input name="email" className="text-black" />
<label htmlFor="password">Password</label>
<input type="password" name="password" className="text-black" />
<button>Sign In</button>
</form>
);
}
if adding redirect: "follow" doesnt work then try this
"use client";
import { useRouter } from "next/navigation";
export default function Login() {
const router = useRouter()
return (
<form
onSubmit={async (e) => {
e.preventDefault();
const res = await fetch("/auth/login", {
method: "POST",
redirect: "follow",
body: new FormData(e.currentTarget),
});
if (res.status === 301) {
router.push(res.url)
}
}}
>
<label htmlFor="email">Email</label>
<input name="email" className="text-black" />
<label htmlFor="password">Password</label>
<input type="password" name="password" className="text-black" />
<button>Sign In</button>
</form>
);
}Brown bearOP
fetch occuring but
when i do on a new browser window nothing
but
when i did on browser window wihch already has login cookie stored or something
got this in console
@Brown bear Click to see attachment
invalid login credential
Brown bearOP
that was in browser session i already had cookie saved
because i logged in previously
before i added middleware and other stuff
but i was logged in and went back to /login and tried loggin in again and got that
but i put in right password and retried on other browser session and it has same issue as before
do you see correct email and password logged with this line?
console.log(email, password);Brown bearOP
where would i log that
Brown bearOP
no dont see anything logged