Next.js Endpoint compiles then returns 404

Problem:
I have a server-sent-events route on my nextjs application which is running locally. This route is in this path: (using App Router)

‘src/app/api/ai/embeddings/generate/route.ts’

I’m creating a new EventSource on the frontend as follows:

const eventSource = new EventSource("/api/ai/embeddings/generate");

For a long time this was working fine, suddenly, without any change to how the requests are made or received, the route started returning 404 when requested.

The only changes made that day were to a function inside this route. However I can confirm that it wasn’t the issue as I used a previous commit to revert the changes, yet the issue persisted.

Attempted Solutions:

At first I tried console logging at the top of the route, however I never saw the log in my terminal (I also double checked the browser console, no logs either).

I then moved on to reverting any changes made to that route and testing again, however the issue persisted.

When I create a dumb route with just a response, something like this:

import { NextResponse } from "next/server";

export async function GET() {
  return new Response("/api/ai/embeddings/generate route working!");
}

and then go to that url in the browser, I can see the message. (sometimes I didn’t see it, but since I didn’t find the cause I assume it’s just the .next local server not updating quick enough)

Code:

Below is the relevant code:

Backend

export async function GET() {
	try {
		const user = await authorized();

		if (!user) return NextResponse.json({ msg: "Unauthorized" }, { status: 401 });

		const supabase = await createClient();

		const embeddingStatus: Record<Enums<"embedding">, boolean> = { website: false, file: false, text: false, qa: false, notion: false };

		const stream = new ReadableStream({
			async start(controller) {
				const pushUpdate = (data: { type: any; status: string; error?: string }) => {
					controller.enqueue(new TextEncoder().encode(`data: ${JSON.stringify(data)}\n\n`));
				};

				const handleEmbeddingGeneration = async (
					type: Enums<"embedding">,
					generatorFunction: (supabase: SupabaseClient, user: User) => Promise<true | null>
				) => {
					try {
						const embeddings: true | null = await generatorFunction(supabase, user);
						embeddingStatus[type] = embeddings ? true : false;
						pushUpdate({ type, status: embeddings ? "completed" : "skipped" });
					} catch (err: unknown) {
						const error = err as { message: string };
						embeddingStatus[type] = false;
						pushUpdate({ type, status: "error", error: error.message });
					}
				};

				await Promise.all([
					handleEmbeddingGeneration("website", generate_website_embed),
					handleEmbeddingGeneration("file", generate_file_embed),
					handleEmbeddingGeneration("text", generate_text_embed),
					handleEmbeddingGeneration("qa", generate_qa_embed),
					handleEmbeddingGeneration("notion", generate_notion_embed),
				]);

				const { data, error } = await supabase.from("embedding_history").insert({
					embeddings: embeddingStatus,
					user: user.id,
				});

				if (error) console.error(error);

				controller.close();
			},
		});

		return new Response(stream, {
			headers: {
				"Content-Type": "text/event-stream",
				"Cache-Control": "no-cache",
				Connection: "keep-alive",
			},
		});
	} catch (err) {
		console.error(err);
		return NextResponse.json({ msg: "Unexpected error occurred" }, { status: 500 });
	}
}

Frontend

async function generateEmbeddings(e: React.MouseEvent<HTMLButtonElement>) {
		e.preventDefault();
		try {
			setShowEmbeddingMessage(true);
			const eventSource = new EventSource("/api/ai/embeddings/generate");

			eventSource.onmessage = (event) => {
				const data = JSON.parse(event.data);
				console.log(data);
				setEmbeddingStatus((prev) => ({
					...prev,
					[data.type]: data.status === "completed",
				}));
			};

			eventSource.onerror = () => {
				eventSource.close();
				dispatch(
					addToast({
						type: "error",
						description: "Unexpected error occurred.",
					})
				);
				setShowEmbeddingMessage(false);
			};
		} catch (err: unknown) {
			const error = err as { msg: string };
			if (error) console.error(error);
			dispatch(
				addToast({
					type: "error",
					description: error.msg || "An unexpected error occurred.",
				})
			);
			setShowEmbeddingMessage(false);
		}
	}

Project Information:

next: 15.1.7

There’s another community post with 404 debugging tips that might be helpful. Please give these solutions a try and let us know how it goes.

A human should be around soon to offer more advice. But you can also get helpful information quickly by asking v0.

Do you have a deployed preview that shows the 404?

If you have deployment protection enabled, make sure you get a shareable link so we can see the preview

I don’t have a deployment at the moment, this issue is happening in local development.

We have found the cause of the issue and were thankfully able to solve it.

The issue was a library named pdf-parse that uses nodejs specific features, I had to add it to the serverExternalPackages next.config.mjs file, which I did not.

After adding it to the serverExternalPackages configuration, the endpoint runs smoothly.

1 Like

Thank you for coming back to share the solution! I’m glad you got it working :smiley:

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.