From 520fa895861ba59847f73d220e70d521aba65fbd Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Thu, 19 Mar 2026 21:41:33 -0700 Subject: [PATCH 1/2] fix(server): exclude stack trace from REST generic error responses Remove stack trace from error messages returned to clients to avoid leaking internal implementation details. Co-Authored-By: Claude Opus 4.6 --- packages/server/src/api/rest/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/src/api/rest/index.ts b/packages/server/src/api/rest/index.ts index c2723f061..e39606d1c 100644 --- a/packages/server/src/api/rest/index.ts +++ b/packages/server/src/api/rest/index.ts @@ -505,7 +505,7 @@ export class RestApiHandler implements Api } private handleGenericError(err: unknown): Response | PromiseLike { - return this.makeError('unknownError', err instanceof Error ? `${err.message}\n${err.stack}` : 'Unknown error'); + return this.makeError('unknownError', err instanceof Error ? `${err.message}` : 'Unknown error'); } private async processProcedureRequest({ From e449af65460c36dc6e56844e91145753186a387e Mon Sep 17 00:00:00 2001 From: ymc9 <104139426+ymc9@users.noreply.github.com> Date: Fri, 20 Mar 2026 10:16:36 -0700 Subject: [PATCH 2/2] improve error logging --- packages/server/src/api/rest/index.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/packages/server/src/api/rest/index.ts b/packages/server/src/api/rest/index.ts index a645a9aa0..651a98736 100644 --- a/packages/server/src/api/rest/index.ts +++ b/packages/server/src/api/rest/index.ts @@ -1,4 +1,4 @@ -import { clone, enumerate, lowerCaseFirst, paramCase } from '@zenstackhq/common-helpers'; +import { clone, enumerate, lowerCaseFirst, paramCase, safeJSONStringify } from '@zenstackhq/common-helpers'; import { ORMError, ORMErrorReason, type ClientContract } from '@zenstackhq/orm'; import type { FieldDef, ModelDef, SchemaDef } from '@zenstackhq/orm/schema'; import { Decimal } from 'decimal.js'; @@ -508,7 +508,13 @@ export class RestApiHandler implements Api } private handleGenericError(err: unknown): Response | PromiseLike { - return this.makeError('unknownError', err instanceof Error ? `${err.message}` : 'Unknown error'); + const resp = this.makeError('unknownError', err instanceof Error ? `${err.message}` : 'Unknown error'); + log( + this.options.log, + 'debug', + () => `sending error response: ${safeJSONStringify(resp)}${err instanceof Error ? '\n' + err.stack : ''}`, + ); + return resp; } private async processProcedureRequest({ @@ -585,14 +591,18 @@ export class RestApiHandler implements Api private makeProcBadInputErrorResponse(message: string): Response { const resp = this.makeError('invalidPayload', message, 400); - log(this.log, 'debug', () => `sending error response: ${JSON.stringify(resp)}`); + log(this.log, 'debug', () => `sending error response: ${safeJSONStringify(resp)}`); return resp; } private makeProcGenericErrorResponse(err: unknown): Response { const message = err instanceof Error ? err.message : 'unknown error'; const resp = this.makeError('unknownError', message, 500); - log(this.log, 'debug', () => `sending error response: ${JSON.stringify(resp)}`); + log( + this.log, + 'debug', + () => `sending error response: ${safeJSONStringify(resp)}${err instanceof Error ? '\n' + err.stack : ''}`, + ); return resp; }