T
TanStack•6mo ago
fascinating-indigo

Cannot read properties of undefined (reading 'result')

I kept getting this random error on my loader function so I changed it to a before load and I keep getting the exact same error. Its so weird because I can't even catch the bloody error. If I place a try catch over my entire fn it still throws. This is the entire error:
TypeError: Cannot read properties of undefined (reading 'result')
at eval (/home/tmx/personal/heikecspvpay/node_modules/@tanstack/start-server-functions-handler/dist/esm/index.js:93:18)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async handleServerRequest (/home/tmx/personal/heikecspvpay/node_modules/@tanstack/start-server-functions-handler/dist/esm/index.js:68:20)
at async handleServerAction (/home/tmx/personal/heikecspvpay/node_modules/@tanstack/start-server-functions-handler/dist/esm/index.js:13:20)
at async _callHandler (file:///home/tmx/personal/heikecspvpay/node_modules/h3/dist/index.mjs:1837:16)
at async file:///home/tmx/personal/heikecspvpay/node_modules/h3/dist/index.mjs:1978:19
at async Object.callAsync (file:///home/tmx/personal/heikecspvpay/node_modules/unctx/dist/index.mjs:72:16)
at async toNodeHandle (file:///home/tmx/personal/heikecspvpay/node_modules/h3/dist/index.mjs:2270:7)
at async ufetch (file:///home/tmx/personal/heikecspvpay/node_modules/unenv/runtime/fetch/index.mjs:9:17)
at async eval (/home/tmx/personal/heikecspvpay/node_modules/@tanstack/start-server-functions-ssr/dist/esm/index.js:14:19)
at async serverFnFetcher (/home/tmx/personal/heikecspvpay/node_modules/@tanstack/start-server-functions-fetcher/dist/esm/index.js:57:47)
at async Object.beforeLoad (/home/tmx/personal/heikecspvpay/src/routes/success.tsx:64:7)
at async file:///home/tmx/personal/heikecspvpay/node_modules/@tanstack/react-router/dist/esm/router.js:998:47
TypeError: Cannot read properties of undefined (reading 'result')
at eval (/home/tmx/personal/heikecspvpay/node_modules/@tanstack/start-server-functions-handler/dist/esm/index.js:93:18)
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async handleServerRequest (/home/tmx/personal/heikecspvpay/node_modules/@tanstack/start-server-functions-handler/dist/esm/index.js:68:20)
at async handleServerAction (/home/tmx/personal/heikecspvpay/node_modules/@tanstack/start-server-functions-handler/dist/esm/index.js:13:20)
at async _callHandler (file:///home/tmx/personal/heikecspvpay/node_modules/h3/dist/index.mjs:1837:16)
at async file:///home/tmx/personal/heikecspvpay/node_modules/h3/dist/index.mjs:1978:19
at async Object.callAsync (file:///home/tmx/personal/heikecspvpay/node_modules/unctx/dist/index.mjs:72:16)
at async toNodeHandle (file:///home/tmx/personal/heikecspvpay/node_modules/h3/dist/index.mjs:2270:7)
at async ufetch (file:///home/tmx/personal/heikecspvpay/node_modules/unenv/runtime/fetch/index.mjs:9:17)
at async eval (/home/tmx/personal/heikecspvpay/node_modules/@tanstack/start-server-functions-ssr/dist/esm/index.js:14:19)
at async serverFnFetcher (/home/tmx/personal/heikecspvpay/node_modules/@tanstack/start-server-functions-fetcher/dist/esm/index.js:57:47)
at async Object.beforeLoad (/home/tmx/personal/heikecspvpay/src/routes/success.tsx:64:7)
at async file:///home/tmx/personal/heikecspvpay/node_modules/@tanstack/react-router/dist/esm/router.js:998:47
I have identified that the error occurs after I try to update some stuff on a google sheet. But its weird because the update goes through perfectly
8 Replies
flat-fuchsia
flat-fuchsia•6mo ago
please share your code
fascinating-indigo
fascinating-indigoOP•6mo ago
@Manuel Schiller here, it got more complicated than needed bc I keep trying to catch the error 😦
export const Route = createFileRoute("/success")({
component: RouteComponent,
validateSearch: z.object({
sessionId: z.string(),
editionId: z.string(),
}),
beforeLoad: async ({ search }) => {
const { sessionId, editionId } = search;
try {
const stripe = new Stripe(env.STRIPE_SECRET_KEY, {
apiVersion: "2025-02-24.acacia",
});

async function getSession() {
const maxRetries = 5;
const baseDelay = 500; //

for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const session = await stripe.checkout.sessions.retrieve(sessionId);
return session;
} catch (error) {
if (attempt === maxRetries - 1) throw error;

// Exponential backoff: 1s, 2s, 4s
const delay = baseDelay * Math.pow(2, attempt);
await new Promise((resolve) => setTimeout(resolve, delay));
}
}
}

const session = await getSession();
if (!session) {
throw redirect({ href: env.ERROR_PAGE_URL });
}
// continues below
export const Route = createFileRoute("/success")({
component: RouteComponent,
validateSearch: z.object({
sessionId: z.string(),
editionId: z.string(),
}),
beforeLoad: async ({ search }) => {
const { sessionId, editionId } = search;
try {
const stripe = new Stripe(env.STRIPE_SECRET_KEY, {
apiVersion: "2025-02-24.acacia",
});

async function getSession() {
const maxRetries = 5;
const baseDelay = 500; //

for (let attempt = 0; attempt < maxRetries; attempt++) {
try {
const session = await stripe.checkout.sessions.retrieve(sessionId);
return session;
} catch (error) {
if (attempt === maxRetries - 1) throw error;

// Exponential backoff: 1s, 2s, 4s
const delay = baseDelay * Math.pow(2, attempt);
await new Promise((resolve) => setTimeout(resolve, delay));
}
}
}

const session = await getSession();
if (!session) {
throw redirect({ href: env.ERROR_PAGE_URL });
}
// continues below
const cols: Customer = {
edition_id: editionId,
email:
session.customer_email ??
session.customer_details?.email ??
"No email",
name: session.customer_details?.name ?? "No name",
preinscription_amount: ((session.amount_total || 0) / 100).toFixed(2),
status: session.payment_status ?? "unknown",
last_update: new Date().toISOString(),
stripe_payment_id:
typeof session.payment_intent === "string"
? session.payment_intent
: session.id,
// preinscription_currency: session.currency || "EUR",
};
if (cols.status !== "paid") {
console.log("Payment not successful");
console.log(session);
throw redirect({ href: env.ERROR_PAGE_URL });
}

await sendPreinscriptionEmail({
name: session.customer_details?.name,
email: cols.email,
editionId,
templateId: env.PREINSCRIPTION_EMAIL_TEMPLATE_ID,
});

console.log("SENT EMAIL");

try {
await updateCustomersList(cols);
} catch (e) {
console.error(e);
throw redirect({ href: env.SUCCESS_PAGE_URL });
}
} catch (error) {
console.error(error);
throw redirect({ href: env.ERROR_PAGE_URL });
}
throw redirect({ href: env.SUCCESS_PAGE_URL });
},
});

function RouteComponent() {
return <div>Loading...</div>;
}
const cols: Customer = {
edition_id: editionId,
email:
session.customer_email ??
session.customer_details?.email ??
"No email",
name: session.customer_details?.name ?? "No name",
preinscription_amount: ((session.amount_total || 0) / 100).toFixed(2),
status: session.payment_status ?? "unknown",
last_update: new Date().toISOString(),
stripe_payment_id:
typeof session.payment_intent === "string"
? session.payment_intent
: session.id,
// preinscription_currency: session.currency || "EUR",
};
if (cols.status !== "paid") {
console.log("Payment not successful");
console.log(session);
throw redirect({ href: env.ERROR_PAGE_URL });
}

await sendPreinscriptionEmail({
name: session.customer_details?.name,
email: cols.email,
editionId,
templateId: env.PREINSCRIPTION_EMAIL_TEMPLATE_ID,
});

console.log("SENT EMAIL");

try {
await updateCustomersList(cols);
} catch (e) {
console.error(e);
throw redirect({ href: env.SUCCESS_PAGE_URL });
}
} catch (error) {
console.error(error);
throw redirect({ href: env.ERROR_PAGE_URL });
}
throw redirect({ href: env.SUCCESS_PAGE_URL });
},
});

function RouteComponent() {
return <div>Loading...</div>;
}
flat-fuchsia
flat-fuchsia•6mo ago
I don't see any server functions being defined
fascinating-indigo
fascinating-indigoOP•6mo ago
No server function is defined anywhere I call two functions that are in external files Aaah, that might be the issue right? beforeLoad might run on the client which means I should wrap all this logic in a server fn
flat-fuchsia
flat-fuchsia•6mo ago
the error states that there are server functions involved
fascinating-indigo
fascinating-indigoOP•6mo ago
I guess it is refering to updateCustomersList & sendPreinscriptionEmail. They arent defined as server functions but I think I have fileName.server.ts Sheets is literally this:
export async function getDoc(docId: string) {
const serviceAccountAuth = new JWT({
// env var values here are copied from service account credentials generated by google
// see "Authentication" section in docs for more info
email: env.GOOGLE_SERVICE_ACCOUNT_EMAIL,
key: env.GOOGLE_PRIVATE_KEY,
scopes: ["https://www.googleapis.com/auth/spreadsheets"],
});

const doc = new GoogleSpreadsheet(
env.GOOGLE_SHEET_DOC_ID,
serviceAccountAuth
);

await doc.loadInfo(); // loads document properties and worksheets
return doc;
}

export async function updateCustomersList(cols: Customer) {
const doc = await getDoc(env.GOOGLE_SHEET_DOC_ID);
const sheet = doc.sheetsByTitle[env.CUSTOMER_LIST_GOOGLE_SHEET_PAGE];
// await sheet.loadHeaderRow();
await sheet.addRow(cols);
}
export async function getDoc(docId: string) {
const serviceAccountAuth = new JWT({
// env var values here are copied from service account credentials generated by google
// see "Authentication" section in docs for more info
email: env.GOOGLE_SERVICE_ACCOUNT_EMAIL,
key: env.GOOGLE_PRIVATE_KEY,
scopes: ["https://www.googleapis.com/auth/spreadsheets"],
});

const doc = new GoogleSpreadsheet(
env.GOOGLE_SHEET_DOC_ID,
serviceAccountAuth
);

await doc.loadInfo(); // loads document properties and worksheets
return doc;
}

export async function updateCustomersList(cols: Customer) {
const doc = await getDoc(env.GOOGLE_SHEET_DOC_ID);
const sheet = doc.sheetsByTitle[env.CUSTOMER_LIST_GOOGLE_SHEET_PAGE];
// await sheet.loadHeaderRow();
await sheet.addRow(cols);
}
Okay literally what I said. Weird but ok. It works if I wrap everything in a serverfn. Can you confirm that beforeLoad can run on the client?
flat-fuchsia
flat-fuchsia•6mo ago
yes sure it runs on the client as well as loader initial SSR runs all on the server subsequent client navigations everything runs on the client
fascinating-indigo
fascinating-indigoOP•6mo ago
Alright. perfect. Yea my bad on the mental model. thanks!

Did you find this page helpful?