I’ve got a weird bug.
I’m creating a web app with Next.js, and I’m hosting it on Vercel.
I created a class called AdminTopicRepository
. When I call new AdminTopicRepository()
, the error Maximum call stack size exceeded
happenes only in Vercel. Yes, I cannot see this error with npx next start
on local environment.
I called only constructor, like this
// ...
export default async function Layout({ children }: { children: ReactNode }) {
new AdminTopicRepository();
return (
// ...
);
}
And after I removed new AdminTopicRepository
statement, no error happened.
Error log from Vercel:
⨯ RangeError: Maximum call stack size exceeded
at Object.mkdirSync (node:fs:1358:19)
at n (/var/task/.next/server/chunks/561.js:7:28582)
at n ...
at n ...
And the class constains only method, does not have setter or getter.
adminTopicRepository.ts:
import { ITopicRepository } from '@/infrastructure/topic/ITopicRepository';
import { Admin } from '@/firebaseAdmin';
import { firestore } from 'firebase-admin';
import { Timestamp } from 'firebase/firestore';
import { Topic } from '@/domain/topic';
import { ForCreateWithId, ForUpdate } from '@/domain/_utils';
import { logger } from '@/logger';
import { adminTopicConverter } from '@/infrastructure/topic/adminTopicConverter';
export class AdminTopicRepository implements ITopicRepository {
private readonly colRef = () =>
Admin.db.collection('topics').withConverter(adminTopicConverter);
private readonly docRef = (topicId: string) =>
Admin.db.doc(`topics/${topicId}`).withConverter(adminTopicConverter);
async create(topic: ForCreateWithId<Topic>): Promise<Topic> {
try {
await this.colRef()
.doc(topic.id)
.set({
...topic,
created_at: firestore.FieldValue.serverTimestamp(),
updated_at: firestore.FieldValue.serverTimestamp(),
});
logger.log(`Topic created. (${topic.id})`);
return {
...topic,
id: topic.id,
created_at: Timestamp.now(),
updated_at: Timestamp.now(),
};
} catch (e) {
logger.error(e);
return Promise.reject(e);
}
}
async delete(id: string): Promise<void> {
try {
await this.docRef(id).delete();
} catch (e) {
logger.error(e);
return Promise.reject(e);
}
}
async find(id: string): Promise<Topic | undefined> {
try {
console.log("Getting topic...")
const snapshot = await this.docRef(id).get();
console.log("Got topic.");
return snapshot.data();
} catch (e) {
logger.error(e);
return Promise.reject(e);
}
}
async findMany(): Promise<Topic[]> {
try {
const snapshot = await this.colRef().get();
return snapshot.docs.map((doc) => doc.data());
} catch (e) {
logger.error(e);
return Promise.reject(e);
}
}
async update(topic: ForUpdate<Topic>): Promise<void> {
try {
await this.docRef(topic.id).update({
...topic,
updated_at: firestore.FieldValue.serverTimestamp(),
});
} catch (e) {
logger.error(e);
return Promise.reject(e);
}
}
}
Next.js is literally magic. How can I fix this?
I added empty constructor()
method to AdminTopicRepository, but nothing changed.