Improve userFriendlyMessage devX (#16815)

Two challenges with error messages
- always provide a useful/meaningful error message for the end user
instead of the generic one. eg: show "Wrong password" and not "An error
occured"
- avoid technical details unless error regards a technical feature. eg:
show "An error occured" and not "Invalid post-hook payload."; but do
show "Invalid issuer URL." as it occurs while configuring SSO

What this PR does
- Make userFriendlyMessage mandatory for widely used
GraphqlQueryRunnerException and CommonQueryRunnerException, so that
developers are forced to ask themselves what the error message should
be, and as it contains very wide error codes (eg: "Bad request") which
should not be mapped to just one default message
- Keep userFriendlyMessage optional for service-specific exceptions (eg:
workflowStepExecutorException), but convert the error code to
userFriendlyMessage mapper to a switch case function with a typecheck
ensuring that all codes are mapped to a message. These default messages
are still overridable where they are thrown.
This commit is contained in:
Marie
2025-12-30 10:08:43 +01:00
committed by GitHub
parent 7522ff6675
commit 19c9f957b1
135 changed files with 1672 additions and 845 deletions
@@ -1,6 +1,5 @@
import { Inject, Injectable } from '@nestjs/common';
import { msg } from '@lingui/core/macro';
import { type PermissionFlagType } from 'twenty-shared/constants';
import { isDefined } from 'twenty-shared/utils';
@@ -13,6 +12,7 @@ import {
CommonQueryRunnerException,
CommonQueryRunnerExceptionCode,
} from 'src/engine/api/common/common-query-runners/errors/common-query-runner.exception';
import { STANDARD_ERROR_MESSAGE } from 'src/engine/api/common/common-query-runners/errors/standard-error-message.constant';
import { CommonResultGettersService } from 'src/engine/api/common/common-result-getters/common-result-getters.service';
import { CommonBaseQueryRunnerContext } from 'src/engine/api/common/types/common-base-query-runner-context.type';
import { CommonExtendedQueryRunnerContext } from 'src/engine/api/common/types/common-extended-query-runner-context.type';
@@ -104,6 +104,7 @@ export abstract class CommonBaseQueryRunnerService<
throw new CommonQueryRunnerException(
'Invalid auth context',
CommonQueryRunnerExceptionCode.INVALID_AUTH_CONTEXT,
{ userFriendlyMessage: STANDARD_ERROR_MESSAGE },
);
}
@@ -315,6 +316,7 @@ export abstract class CommonBaseQueryRunnerService<
throw new CommonQueryRunnerException(
'Invalid auth context',
CommonQueryRunnerExceptionCode.INVALID_AUTH_CONTEXT,
{ userFriendlyMessage: STANDARD_ERROR_MESSAGE },
);
}
@@ -414,7 +416,7 @@ export abstract class CommonBaseQueryRunnerService<
`Query complexity is too high. One-to-Many relation cannot be nested in another One-to-Many relation.`,
CommonQueryRunnerExceptionCode.TOO_COMPLEX_QUERY,
{
userFriendlyMessage: msg`Query complexity is too high. One-to-Many relation cannot be nested in another One-to-Many relation.`,
userFriendlyMessage: STANDARD_ERROR_MESSAGE,
},
);
}
@@ -429,7 +431,7 @@ export abstract class CommonBaseQueryRunnerService<
`Query complexity is too high. Please, reduce the amount of relation fields requested. Query complexity: ${queryComplexity}. Maximum complexity: ${maximumComplexity}.`,
CommonQueryRunnerExceptionCode.TOO_COMPLEX_QUERY,
{
userFriendlyMessage: msg`Query complexity is too high. Please, reduce the amount of relation fields requested. Query complexity: ${queryComplexity}. Maximum complexity: ${maximumComplexity}.`,
userFriendlyMessage: STANDARD_ERROR_MESSAGE,
},
);
}
@@ -17,6 +17,7 @@ import {
CommonQueryRunnerException,
CommonQueryRunnerExceptionCode,
} from 'src/engine/api/common/common-query-runners/errors/common-query-runner.exception';
import { STANDARD_ERROR_MESSAGE } from 'src/engine/api/common/common-query-runners/errors/standard-error-message.constant';
import { CommonBaseQueryRunnerContext } from 'src/engine/api/common/types/common-base-query-runner-context.type';
import { CommonExtendedQueryRunnerContext } from 'src/engine/api/common/types/common-extended-query-runner-context.type';
import {
@@ -467,6 +468,7 @@ export class CommonCreateManyQueryRunnerService extends CommonBaseQueryRunnerSer
throw new CommonQueryRunnerException(
`Missing createdBy field metadata for object ${flatObjectMetadata.nameSingular}`,
CommonQueryRunnerExceptionCode.MISSING_SYSTEM_FIELD,
{ userFriendlyMessage: STANDARD_ERROR_MESSAGE },
);
}
@@ -12,6 +12,7 @@ import {
CommonQueryRunnerException,
CommonQueryRunnerExceptionCode,
} from 'src/engine/api/common/common-query-runners/errors/common-query-runner.exception';
import { STANDARD_ERROR_MESSAGE } from 'src/engine/api/common/common-query-runners/errors/standard-error-message.constant';
import { CommonBaseQueryRunnerContext } from 'src/engine/api/common/types/common-base-query-runner-context.type';
import { CommonExtendedQueryRunnerContext } from 'src/engine/api/common/types/common-extended-query-runner-context.type';
import {
@@ -139,6 +140,7 @@ export class CommonDeleteManyQueryRunnerService extends CommonBaseQueryRunnerSer
throw new CommonQueryRunnerException(
'Filter is required',
CommonQueryRunnerExceptionCode.INVALID_QUERY_INPUT,
{ userFriendlyMessage: STANDARD_ERROR_MESSAGE },
);
}
@@ -1,5 +1,6 @@
import { Injectable } from '@nestjs/common';
import { msg } from '@lingui/core/macro';
import { type ObjectRecord } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
@@ -54,6 +55,9 @@ export class CommonDeleteOneQueryRunnerService extends CommonBaseQueryRunnerServ
throw new CommonQueryRunnerException(
'Record not found',
CommonQueryRunnerExceptionCode.RECORD_NOT_FOUND,
{
userFriendlyMessage: msg`This record does not exist or has been deleted.`,
},
);
}
@@ -12,6 +12,7 @@ import {
CommonQueryRunnerException,
CommonQueryRunnerExceptionCode,
} from 'src/engine/api/common/common-query-runners/errors/common-query-runner.exception';
import { STANDARD_ERROR_MESSAGE } from 'src/engine/api/common/common-query-runners/errors/standard-error-message.constant';
import { CommonBaseQueryRunnerContext } from 'src/engine/api/common/types/common-base-query-runner-context.type';
import { CommonExtendedQueryRunnerContext } from 'src/engine/api/common/types/common-extended-query-runner-context.type';
import {
@@ -140,6 +141,7 @@ export class CommonDestroyManyQueryRunnerService extends CommonBaseQueryRunnerSe
throw new CommonQueryRunnerException(
'Filter is required',
CommonQueryRunnerExceptionCode.INVALID_QUERY_INPUT,
{ userFriendlyMessage: STANDARD_ERROR_MESSAGE },
);
}
@@ -1,5 +1,6 @@
import { Injectable } from '@nestjs/common';
import { msg } from '@lingui/core/macro';
import { type ObjectRecord } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
@@ -11,6 +12,7 @@ import {
CommonQueryRunnerException,
CommonQueryRunnerExceptionCode,
} from 'src/engine/api/common/common-query-runners/errors/common-query-runner.exception';
import { STANDARD_ERROR_MESSAGE } from 'src/engine/api/common/common-query-runners/errors/standard-error-message.constant';
import { CommonBaseQueryRunnerContext } from 'src/engine/api/common/types/common-base-query-runner-context.type';
import { CommonExtendedQueryRunnerContext } from 'src/engine/api/common/types/common-extended-query-runner-context.type';
import {
@@ -52,6 +54,9 @@ export class CommonDestroyOneQueryRunnerService extends CommonBaseQueryRunnerSer
throw new CommonQueryRunnerException(
'Record not found',
CommonQueryRunnerExceptionCode.RECORD_NOT_FOUND,
{
userFriendlyMessage: msg`This record does not exist or has been deleted.`,
},
);
}
@@ -89,6 +94,7 @@ export class CommonDestroyOneQueryRunnerService extends CommonBaseQueryRunnerSer
throw new CommonQueryRunnerException(
'Missing id',
CommonQueryRunnerExceptionCode.INVALID_QUERY_INPUT,
{ userFriendlyMessage: STANDARD_ERROR_MESSAGE },
);
}
}
@@ -16,6 +16,7 @@ import {
CommonQueryRunnerException,
CommonQueryRunnerExceptionCode,
} from 'src/engine/api/common/common-query-runners/errors/common-query-runner.exception';
import { STANDARD_ERROR_MESSAGE } from 'src/engine/api/common/common-query-runners/errors/standard-error-message.constant';
import { CommonBaseQueryRunnerContext } from 'src/engine/api/common/types/common-base-query-runner-context.type';
import { CommonExtendedQueryRunnerContext } from 'src/engine/api/common/types/common-extended-query-runner-context.type';
import { CommonFindDuplicatesOutputItem } from 'src/engine/api/common/types/common-find-duplicates-output-item.type';
@@ -232,6 +233,7 @@ export class CommonFindDuplicatesQueryRunnerService extends CommonBaseQueryRunne
throw new CommonQueryRunnerException(
'You have to provide either "data" or "ids" argument',
CommonQueryRunnerExceptionCode.INVALID_QUERY_INPUT,
{ userFriendlyMessage: STANDARD_ERROR_MESSAGE },
);
}
@@ -239,6 +241,7 @@ export class CommonFindDuplicatesQueryRunnerService extends CommonBaseQueryRunne
throw new CommonQueryRunnerException(
'You cannot provide both "data" and "ids" arguments',
CommonQueryRunnerExceptionCode.INVALID_QUERY_INPUT,
{ userFriendlyMessage: STANDARD_ERROR_MESSAGE },
);
}
@@ -246,6 +249,7 @@ export class CommonFindDuplicatesQueryRunnerService extends CommonBaseQueryRunne
throw new CommonQueryRunnerException(
'The "data" condition can not be empty when "ids" input not provided',
CommonQueryRunnerExceptionCode.INVALID_QUERY_INPUT,
{ userFriendlyMessage: STANDARD_ERROR_MESSAGE },
);
}
}
@@ -19,6 +19,7 @@ import {
CommonQueryRunnerException,
CommonQueryRunnerExceptionCode,
} from 'src/engine/api/common/common-query-runners/errors/common-query-runner.exception';
import { STANDARD_ERROR_MESSAGE } from 'src/engine/api/common/common-query-runners/errors/standard-error-message.constant';
import { CommonBaseQueryRunnerContext } from 'src/engine/api/common/types/common-base-query-runner-context.type';
import { CommonExtendedQueryRunnerContext } from 'src/engine/api/common/types/common-extended-query-runner-context.type';
import { CommonFindManyOutput } from 'src/engine/api/common/types/common-find-many-output.type';
@@ -235,36 +236,42 @@ export class CommonFindManyQueryRunnerService extends CommonBaseQueryRunnerServi
throw new CommonQueryRunnerException(
'Cannot provide both first and last',
CommonQueryRunnerExceptionCode.ARGS_CONFLICT,
{ userFriendlyMessage: STANDARD_ERROR_MESSAGE },
);
}
if (args.before && args.after) {
throw new CommonQueryRunnerException(
'Cannot provide both before and after',
CommonQueryRunnerExceptionCode.ARGS_CONFLICT,
{ userFriendlyMessage: STANDARD_ERROR_MESSAGE },
);
}
if (args.before && args.first) {
throw new CommonQueryRunnerException(
'Cannot provide both before and first',
CommonQueryRunnerExceptionCode.ARGS_CONFLICT,
{ userFriendlyMessage: STANDARD_ERROR_MESSAGE },
);
}
if (args.after && args.last) {
throw new CommonQueryRunnerException(
'Cannot provide both after and last',
CommonQueryRunnerExceptionCode.ARGS_CONFLICT,
{ userFriendlyMessage: STANDARD_ERROR_MESSAGE },
);
}
if (args.first !== undefined && args.first < 0) {
throw new CommonQueryRunnerException(
'First argument must be non-negative',
CommonQueryRunnerExceptionCode.INVALID_ARGS_FIRST,
{ userFriendlyMessage: STANDARD_ERROR_MESSAGE },
);
}
if (args.last !== undefined && args.last < 0) {
throw new CommonQueryRunnerException(
'Last argument must be non-negative',
CommonQueryRunnerExceptionCode.INVALID_ARGS_LAST,
{ userFriendlyMessage: STANDARD_ERROR_MESSAGE },
);
}
}
@@ -1,5 +1,6 @@
import { Injectable } from '@nestjs/common';
import { msg } from '@lingui/core/macro';
import { QUERY_MAX_RECORDS_FROM_RELATION } from 'twenty-shared/constants';
import { ObjectRecord } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
@@ -13,6 +14,7 @@ import {
CommonQueryRunnerException,
CommonQueryRunnerExceptionCode,
} from 'src/engine/api/common/common-query-runners/errors/common-query-runner.exception';
import { STANDARD_ERROR_MESSAGE } from 'src/engine/api/common/common-query-runners/errors/standard-error-message.constant';
import { CommonBaseQueryRunnerContext } from 'src/engine/api/common/types/common-base-query-runner-context.type';
import { CommonExtendedQueryRunnerContext } from 'src/engine/api/common/types/common-extended-query-runner-context.type';
import {
@@ -81,6 +83,9 @@ export class CommonFindOneQueryRunnerService extends CommonBaseQueryRunnerServic
throw new CommonQueryRunnerException(
'Record not found',
CommonQueryRunnerExceptionCode.RECORD_NOT_FOUND,
{
userFriendlyMessage: msg`This record does not exist or has been deleted.`,
},
);
}
@@ -147,6 +152,7 @@ export class CommonFindOneQueryRunnerService extends CommonBaseQueryRunnerServic
throw new CommonQueryRunnerException(
'Missing filter argument',
CommonQueryRunnerExceptionCode.INVALID_QUERY_INPUT,
{ userFriendlyMessage: STANDARD_ERROR_MESSAGE },
);
}
}
@@ -23,6 +23,7 @@ import {
CommonQueryRunnerException,
CommonQueryRunnerExceptionCode,
} from 'src/engine/api/common/common-query-runners/errors/common-query-runner.exception';
import { STANDARD_ERROR_MESSAGE } from 'src/engine/api/common/common-query-runners/errors/standard-error-message.constant';
import { getGroupByDefinitions } from 'src/engine/api/common/common-query-runners/utils/get-group-by-definitions.util';
import { getObjectAlias } from 'src/engine/api/common/common-query-runners/utils/get-object-alias-for-group-by.util';
import { CommonBaseQueryRunnerContext } from 'src/engine/api/common/types/common-base-query-runner-context.type';
@@ -214,6 +215,7 @@ export class CommonGroupByQueryRunnerService extends CommonBaseQueryRunnerServic
throw new CommonQueryRunnerException(
`Field metadata not found for field ${viewFilter.fieldMetadataId}`,
CommonQueryRunnerExceptionCode.INTERNAL_SERVER_ERROR,
{ userFriendlyMessage: STANDARD_ERROR_MESSAGE },
);
}
@@ -363,6 +365,7 @@ export class CommonGroupByQueryRunnerService extends CommonBaseQueryRunnerServic
throw new CommonQueryRunnerException(
`Field metadata settings are missing or invalid for field ${groupByField.fieldMetadata.name}`,
CommonQueryRunnerExceptionCode.INTERNAL_SERVER_ERROR,
{ userFriendlyMessage: STANDARD_ERROR_MESSAGE },
);
}
@@ -1,5 +1,6 @@
import { Injectable, Logger } from '@nestjs/common';
import { msg } from '@lingui/core/macro';
import {
MUTATION_MAX_MERGE_RECORDS,
QUERY_MAX_RECORDS_FROM_RELATION,
@@ -21,6 +22,7 @@ import {
CommonQueryRunnerException,
CommonQueryRunnerExceptionCode,
} from 'src/engine/api/common/common-query-runners/errors/common-query-runner.exception';
import { STANDARD_ERROR_MESSAGE } from 'src/engine/api/common/common-query-runners/errors/standard-error-message.constant';
import { CommonBaseQueryRunnerContext } from 'src/engine/api/common/types/common-base-query-runner-context.type';
import { CommonExtendedQueryRunnerContext } from 'src/engine/api/common/types/common-extended-query-runner-context.type';
import {
@@ -144,6 +146,7 @@ export class CommonMergeManyQueryRunnerService extends CommonBaseQueryRunnerServ
throw new CommonQueryRunnerException(
'One or more records not found',
CommonQueryRunnerExceptionCode.RECORD_NOT_FOUND,
{ userFriendlyMessage: msg`One or more records were not found.` },
);
}
@@ -182,6 +185,9 @@ export class CommonMergeManyQueryRunnerService extends CommonBaseQueryRunnerServ
throw new CommonQueryRunnerException(
'Priority record not found',
CommonQueryRunnerExceptionCode.RECORD_NOT_FOUND,
{
userFriendlyMessage: msg`This record does not exist or has been deleted.`,
},
);
}
@@ -323,6 +329,7 @@ export class CommonMergeManyQueryRunnerService extends CommonBaseQueryRunnerServ
throw new CommonQueryRunnerException(
'Failed to update record',
CommonQueryRunnerExceptionCode.RECORD_NOT_FOUND,
{ userFriendlyMessage: STANDARD_ERROR_MESSAGE },
);
}
@@ -482,6 +489,7 @@ export class CommonMergeManyQueryRunnerService extends CommonBaseQueryRunnerServ
throw new CommonQueryRunnerException(
`Merge is only available for objects with duplicate criteria. Object '${flatObjectMetadata.nameSingular}' does not have duplicate criteria defined.`,
CommonQueryRunnerExceptionCode.INVALID_QUERY_INPUT,
{ userFriendlyMessage: msg`This type of record cannot be merged.` },
);
}
@@ -491,6 +499,9 @@ export class CommonMergeManyQueryRunnerService extends CommonBaseQueryRunnerServ
throw new CommonQueryRunnerException(
'At least 2 record IDs are required for merge',
CommonQueryRunnerExceptionCode.INVALID_QUERY_INPUT,
{
userFriendlyMessage: msg`Please select at least 2 records to merge.`,
},
);
}
@@ -498,6 +509,9 @@ export class CommonMergeManyQueryRunnerService extends CommonBaseQueryRunnerServ
throw new CommonQueryRunnerException(
`Maximum ${MUTATION_MAX_MERGE_RECORDS} records can be merged at once`,
CommonQueryRunnerExceptionCode.INVALID_QUERY_INPUT,
{
userFriendlyMessage: msg`You can merge up to ${MUTATION_MAX_MERGE_RECORDS} records at once.`,
},
);
}
@@ -505,6 +519,7 @@ export class CommonMergeManyQueryRunnerService extends CommonBaseQueryRunnerServ
throw new CommonQueryRunnerException(
`Invalid conflict priority '${conflictPriorityIndex}'. Valid options for ${ids.length} records: 0-${ids.length - 1}`,
CommonQueryRunnerExceptionCode.INVALID_QUERY_INPUT,
{ userFriendlyMessage: STANDARD_ERROR_MESSAGE },
);
}
}
@@ -12,6 +12,7 @@ import {
CommonQueryRunnerException,
CommonQueryRunnerExceptionCode,
} from 'src/engine/api/common/common-query-runners/errors/common-query-runner.exception';
import { STANDARD_ERROR_MESSAGE } from 'src/engine/api/common/common-query-runners/errors/standard-error-message.constant';
import { CommonBaseQueryRunnerContext } from 'src/engine/api/common/types/common-base-query-runner-context.type';
import { CommonExtendedQueryRunnerContext } from 'src/engine/api/common/types/common-extended-query-runner-context.type';
import {
@@ -139,6 +140,7 @@ export class CommonRestoreManyQueryRunnerService extends CommonBaseQueryRunnerSe
throw new CommonQueryRunnerException(
'Filter is required',
CommonQueryRunnerExceptionCode.INVALID_QUERY_INPUT,
{ userFriendlyMessage: STANDARD_ERROR_MESSAGE },
);
}
@@ -1,5 +1,6 @@
import { Injectable } from '@nestjs/common';
import { msg } from '@lingui/core/macro';
import { type ObjectRecord } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
@@ -54,6 +55,9 @@ export class CommonRestoreOneQueryRunnerService extends CommonBaseQueryRunnerSer
throw new CommonQueryRunnerException(
'Record not found',
CommonQueryRunnerExceptionCode.RECORD_NOT_FOUND,
{
userFriendlyMessage: msg`This record does not exist or has been deleted.`,
},
);
}
@@ -12,6 +12,7 @@ import {
CommonQueryRunnerException,
CommonQueryRunnerExceptionCode,
} from 'src/engine/api/common/common-query-runners/errors/common-query-runner.exception';
import { STANDARD_ERROR_MESSAGE } from 'src/engine/api/common/common-query-runners/errors/standard-error-message.constant';
import { CommonBaseQueryRunnerContext } from 'src/engine/api/common/types/common-base-query-runner-context.type';
import { CommonExtendedQueryRunnerContext } from 'src/engine/api/common/types/common-extended-query-runner-context.type';
import {
@@ -133,6 +134,7 @@ export class CommonUpdateManyQueryRunnerService extends CommonBaseQueryRunnerSer
throw new CommonQueryRunnerException(
'Filter is required',
CommonQueryRunnerExceptionCode.INVALID_QUERY_INPUT,
{ userFriendlyMessage: STANDARD_ERROR_MESSAGE },
);
}
@@ -1,5 +1,6 @@
import { Injectable } from '@nestjs/common';
import { msg } from '@lingui/core/macro';
import { type ObjectRecord } from 'twenty-shared/types';
import { WorkspaceAuthContext } from 'src/engine/api/common/interfaces/workspace-auth-context.interface';
@@ -52,6 +53,9 @@ export class CommonUpdateOneQueryRunnerService extends CommonBaseQueryRunnerServ
throw new CommonQueryRunnerException(
'Record not found',
CommonQueryRunnerExceptionCode.RECORD_NOT_FOUND,
{
userFriendlyMessage: msg`This record does not exist or has been deleted.`,
},
);
}
@@ -1,5 +1,4 @@
import { type MessageDescriptor } from '@lingui/core';
import { msg } from '@lingui/core/macro';
import { CustomException } from 'src/utils/custom-exception';
@@ -21,37 +20,14 @@ export enum CommonQueryRunnerExceptionCode {
MISSING_TIMEZONE_FOR_DATE_GROUP_BY = 'MISSING_TIMEZONE_FOR_DATE_GROUP_BY',
}
const commonQueryRunnerExceptionUserFriendlyMessages: Record<
CommonQueryRunnerExceptionCode,
MessageDescriptor
> = {
[CommonQueryRunnerExceptionCode.RECORD_NOT_FOUND]: msg`Record not found.`,
[CommonQueryRunnerExceptionCode.INVALID_QUERY_INPUT]: msg`Invalid query input.`,
[CommonQueryRunnerExceptionCode.INVALID_AUTH_CONTEXT]: msg`Invalid authentication context.`,
[CommonQueryRunnerExceptionCode.ARGS_CONFLICT]: msg`Conflicting arguments provided.`,
[CommonQueryRunnerExceptionCode.INVALID_ARGS_DATA]: msg`Invalid data provided.`,
[CommonQueryRunnerExceptionCode.INVALID_ARGS_FIRST]: msg`Invalid 'first' argument.`,
[CommonQueryRunnerExceptionCode.INVALID_ARGS_LAST]: msg`Invalid 'last' argument.`,
[CommonQueryRunnerExceptionCode.UPSERT_MULTIPLE_MATCHING_RECORDS_CONFLICT]: msg`Multiple matching records found during upsert.`,
[CommonQueryRunnerExceptionCode.MISSING_SYSTEM_FIELD]: msg`Missing required system field.`,
[CommonQueryRunnerExceptionCode.INVALID_CURSOR]: msg`Invalid cursor provided.`,
[CommonQueryRunnerExceptionCode.TOO_MANY_RECORDS_TO_UPDATE]: msg`Too many records to update at once.`,
[CommonQueryRunnerExceptionCode.BAD_REQUEST]: msg`Bad request.`,
[CommonQueryRunnerExceptionCode.INTERNAL_SERVER_ERROR]: msg`An unexpected error occurred.`,
[CommonQueryRunnerExceptionCode.TOO_COMPLEX_QUERY]: msg`Query is too complex.`,
[CommonQueryRunnerExceptionCode.MISSING_TIMEZONE_FOR_DATE_GROUP_BY]: msg`Missing time zone for date group by.`,
};
export class CommonQueryRunnerException extends CustomException<CommonQueryRunnerExceptionCode> {
constructor(
message: string,
code: CommonQueryRunnerExceptionCode,
{ userFriendlyMessage }: { userFriendlyMessage?: MessageDescriptor } = {},
{ userFriendlyMessage }: { userFriendlyMessage: MessageDescriptor },
) {
super(message, code, {
userFriendlyMessage:
userFriendlyMessage ??
commonQueryRunnerExceptionUserFriendlyMessages[code],
userFriendlyMessage,
});
}
}
@@ -0,0 +1,3 @@
import { msg } from '@lingui/core/macro';
export const STANDARD_ERROR_MESSAGE = msg`An error occurred.`;