Skip to content

Commit 3df6ddf

Browse files
committed
start displaying prettier internal errors
1 parent 7403cb5 commit 3df6ddf

File tree

5 files changed

+155
-34
lines changed

5 files changed

+155
-34
lines changed

apps/webapp/app/components/runs/v3/RunInspector.tsx

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
import { CheckIcon, ClockIcon, CloudArrowDownIcon, QueueListIcon } from "@heroicons/react/20/solid";
22
import { Link } from "@remix-run/react";
3-
import { formatDuration, formatDurationMilliseconds, TaskRunError } from "@trigger.dev/core/v3";
3+
import {
4+
formatDuration,
5+
formatDurationMilliseconds,
6+
TaskRunError,
7+
taskRunErrorEnhancer,
8+
} from "@trigger.dev/core/v3";
49
import { useEffect } from "react";
510
import { useTypedFetcher } from "remix-typedjson";
611
import { ExitIcon } from "~/assets/icons/ExitIcon";
@@ -553,32 +558,39 @@ function RunTimeline({ run }: { run: RawRun }) {
553558
}
554559

555560
function RunError({ error }: { error: TaskRunError }) {
556-
switch (error.type) {
561+
const enhancedError = taskRunErrorEnhancer(error);
562+
563+
switch (enhancedError.type) {
557564
case "STRING_ERROR":
558565
case "CUSTOM_ERROR": {
559566
return (
560567
<div className="flex flex-col gap-2 rounded-sm border border-rose-500/50 px-3 pb-3 pt-2">
561568
<CodeBlock
562569
showCopyButton={false}
563570
showLineNumbers={false}
564-
code={error.raw}
571+
code={enhancedError.raw}
565572
maxLines={20}
566573
/>
567574
</div>
568575
);
569576
}
570577
case "BUILT_IN_ERROR":
571578
case "INTERNAL_ERROR": {
572-
const name = "name" in error ? error.name : error.code;
579+
const name = "name" in enhancedError ? enhancedError.name : enhancedError.code;
573580
return (
574581
<div className="flex flex-col gap-2 rounded-sm border border-rose-500/50 px-3 pb-3 pt-2">
575582
<Header3 className="text-rose-500">{name}</Header3>
576-
{error.message && <Callout variant="error">{error.message}</Callout>}
577-
{error.stackTrace && (
583+
{enhancedError.message && <Callout variant="error">{enhancedError.message}</Callout>}
584+
{enhancedError.link && (
585+
<Callout variant="docs" to={enhancedError.link.href}>
586+
{enhancedError.link.name}
587+
</Callout>
588+
)}
589+
{enhancedError.stackTrace && (
578590
<CodeBlock
579591
showCopyButton={false}
580592
showLineNumbers={false}
581-
code={error.stackTrace}
593+
code={enhancedError.stackTrace}
582594
maxLines={20}
583595
/>
584596
)}

apps/webapp/app/components/runs/v3/SpanEvents.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
exceptionEventEnhancer,
23
isExceptionSpanEvent,
34
type ExceptionEventProperties,
45
type SpanEvent as OtelSpanEvent,
@@ -64,19 +65,26 @@ export function SpanEventError({
6465
spanEvent: OtelSpanEvent;
6566
exception: ExceptionEventProperties;
6667
}) {
68+
const enhancedException = exceptionEventEnhancer(exception);
69+
6770
return (
6871
<div className="flex flex-col gap-2 rounded-sm border border-rose-500/50 px-3 pb-3 pt-2">
6972
<SpanEventHeader
70-
title={exception.type ?? "Error"}
73+
title={enhancedException.type ?? "Error"}
7174
time={spanEvent.time}
7275
titleClassName="text-rose-500"
7376
/>
74-
{exception.message && <Callout variant="error">{exception.message}</Callout>}
75-
{exception.stacktrace && (
77+
{enhancedException.message && <Callout variant="error">{enhancedException.message}</Callout>}
78+
{enhancedException.link && (
79+
<Callout variant="docs" to={enhancedException.link.href}>
80+
{enhancedException.link.name}
81+
</Callout>
82+
)}
83+
{enhancedException.stacktrace && (
7684
<CodeBlock
7785
showCopyButton={false}
7886
showLineNumbers={false}
79-
code={exception.stacktrace}
87+
code={enhancedException.stacktrace}
8088
maxLines={20}
8189
/>
8290
)}

apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.v3.$projectParam.runs.$runParam.spans.$spanParam/route.tsx

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
formatDurationMilliseconds,
77
nanosecondsToMilliseconds,
88
TaskRunError,
9+
taskRunErrorEnhancer,
910
} from "@trigger.dev/core/v3";
1011
import { ReactNode, useEffect } from "react";
1112
import { typedjson, useTypedFetcher } from "remix-typedjson";
@@ -933,12 +934,14 @@ function RunTimelineLine({ title, state }: RunTimelineLineProps) {
933934
}
934935

935936
function RunError({ error }: { error: TaskRunError }) {
936-
switch (error.type) {
937+
const enhancedError = taskRunErrorEnhancer(error);
938+
939+
switch (enhancedError.type) {
937940
case "STRING_ERROR":
938941
return (
939942
<div className="flex flex-col gap-2 rounded-sm border border-rose-500/50 px-3 pb-3 pt-2">
940943
<Header3 className="text-rose-500">Error</Header3>
941-
<Callout variant="error">{error.raw}</Callout>
944+
<Callout variant="error">{enhancedError.raw}</Callout>
942945
</div>
943946
);
944947
case "CUSTOM_ERROR": {
@@ -947,24 +950,29 @@ function RunError({ error }: { error: TaskRunError }) {
947950
<CodeBlock
948951
showCopyButton={false}
949952
showLineNumbers={false}
950-
code={error.raw}
953+
code={enhancedError.raw}
951954
maxLines={20}
952955
/>
953956
</div>
954957
);
955958
}
956959
case "BUILT_IN_ERROR":
957960
case "INTERNAL_ERROR": {
958-
const name = "name" in error ? error.name : error.code;
961+
const name = "name" in enhancedError ? enhancedError.name : enhancedError.code;
959962
return (
960963
<div className="flex flex-col gap-2 rounded-sm border border-rose-500/50 px-3 pb-3 pt-2">
961964
<Header3 className="text-rose-500">{name}</Header3>
962-
{error.message && <Callout variant="error">{error.message}</Callout>}
963-
{error.stackTrace && (
965+
{enhancedError.message && <Callout variant="error">{enhancedError.message}</Callout>}
966+
{enhancedError.link && (
967+
<Callout variant="docs" to={enhancedError.link.href}>
968+
{enhancedError.link.name}
969+
</Callout>
970+
)}
971+
{enhancedError.stackTrace && (
964972
<CodeBlock
965973
showCopyButton={false}
966974
showLineNumbers={false}
967-
code={error.stackTrace}
975+
code={enhancedError.stackTrace}
968976
maxLines={20}
969977
/>
970978
)}

packages/core/src/v3/errors.ts

Lines changed: 105 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
import { z } from "zod";
22
import { DeploymentErrorData } from "./schemas/api.js";
33
import { ImportTaskFileErrors, WorkerManifest } from "./schemas/build.js";
4-
import { SerializedError, TaskRunError } from "./schemas/common.js";
4+
import {
5+
SerializedError,
6+
TaskRunError,
7+
TaskRunErrorCodes,
8+
TaskRunInternalError,
9+
} from "./schemas/common.js";
510
import { TaskMetadataFailedToParseData } from "./schemas/messages.js";
11+
import { links } from "./links.js";
12+
import { ExceptionEventProperties } from "./schemas/openTelemetry.js";
613

714
export class AbortTaskRunError extends Error {
815
constructor(message: string) {
@@ -68,27 +75,29 @@ export function createErrorTaskError(error: TaskRunError): any {
6875
}
6976

7077
export function createJsonErrorObject(error: TaskRunError): SerializedError {
71-
switch (error.type) {
78+
const enhancedError = taskRunErrorEnhancer(error);
79+
80+
switch (enhancedError.type) {
7281
case "BUILT_IN_ERROR": {
7382
return {
74-
name: error.name,
75-
message: error.message,
76-
stackTrace: error.stackTrace,
83+
name: enhancedError.name,
84+
message: enhancedError.message,
85+
stackTrace: enhancedError.stackTrace,
7786
};
7887
}
7988
case "STRING_ERROR": {
8089
return {
81-
message: error.raw,
90+
message: enhancedError.raw,
8291
};
8392
}
8493
case "CUSTOM_ERROR": {
8594
return {
86-
message: error.raw,
95+
message: enhancedError.raw,
8796
};
8897
}
8998
case "INTERNAL_ERROR": {
9099
return {
91-
message: `trigger.dev internal error (${error.code})`,
100+
message: `trigger.dev internal error (${enhancedError.code})`,
92101
};
93102
}
94103
}
@@ -303,20 +312,100 @@ export class GracefulExitTimeoutError extends Error {
303312
}
304313
}
305314

315+
const prettyInternalErrors: Partial<
316+
Record<TaskRunInternalError["code"], { message: string; link?: { name: string; href: string } }>
317+
> = {
318+
TASK_PROCESS_OOM_KILLED: {
319+
message:
320+
"Your task ran out of memory. Try increasing the machine specs. If this doesn't fix it there might be a memory leak.",
321+
link: {
322+
name: "Machines",
323+
href: links.docs.machines.home,
324+
},
325+
},
326+
TASK_PROCESS_MAYBE_OOM_KILLED: {
327+
message:
328+
"We think your task ran out of memory, but we can't be certain. If this keeps happening, try increasing the machine specs.",
329+
link: {
330+
name: "Machines",
331+
href: links.docs.machines.home,
332+
},
333+
},
334+
};
335+
336+
type EnhanceError<T extends TaskRunError | ExceptionEventProperties> = T & {
337+
link?: { name: string; href: string };
338+
};
339+
340+
export function taskRunErrorEnhancer(error: TaskRunError): EnhanceError<TaskRunError> {
341+
switch (error.type) {
342+
case "BUILT_IN_ERROR": {
343+
if (error.name === "UnexpectedExitError") {
344+
if (error.message.startsWith("Unexpected exit with code -1")) {
345+
return {
346+
type: "INTERNAL_ERROR",
347+
code: TaskRunErrorCodes.TASK_PROCESS_MAYBE_OOM_KILLED,
348+
...prettyInternalErrors.TASK_PROCESS_MAYBE_OOM_KILLED,
349+
};
350+
}
351+
}
352+
break;
353+
}
354+
case "STRING_ERROR": {
355+
break;
356+
}
357+
case "CUSTOM_ERROR": {
358+
break;
359+
}
360+
case "INTERNAL_ERROR": {
361+
if (error.code === TaskRunErrorCodes.TASK_PROCESS_EXITED_WITH_NON_ZERO_CODE) {
362+
return {
363+
type: "INTERNAL_ERROR",
364+
code: TaskRunErrorCodes.TASK_PROCESS_MAYBE_OOM_KILLED,
365+
...prettyInternalErrors.TASK_PROCESS_MAYBE_OOM_KILLED,
366+
};
367+
}
368+
369+
const prettyError = prettyInternalErrors[error.code];
370+
371+
if (prettyError) {
372+
return {
373+
...error,
374+
...prettyError,
375+
};
376+
}
377+
378+
break;
379+
}
380+
}
381+
382+
return error;
383+
}
384+
385+
export function exceptionEventEnhancer(
386+
exception: ExceptionEventProperties
387+
): EnhanceError<ExceptionEventProperties> {
388+
switch (exception.type) {
389+
case "UnexpectedExitError": {
390+
if (exception.message?.startsWith("Unexpected exit with code -1")) {
391+
return {
392+
...exception,
393+
...prettyInternalErrors.TASK_PROCESS_MAYBE_OOM_KILLED,
394+
};
395+
}
396+
break;
397+
}
398+
}
399+
400+
return exception;
401+
}
402+
306403
export function getFriendlyErrorMessage(
307404
code: number,
308405
signal: NodeJS.Signals | null,
309406
stderr: string | undefined,
310407
dockerMode = true
311408
) {
312-
const message = (text: string) => {
313-
if (signal) {
314-
return `[${signal}] ${text}`;
315-
} else {
316-
return text;
317-
}
318-
};
319-
320409
if (code === 137) {
321410
if (dockerMode) {
322411
return message(

packages/core/src/v3/schemas/common.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ export const TaskRunErrorCodes = {
8787
TASK_EXECUTION_ABORTED: "TASK_EXECUTION_ABORTED",
8888
TASK_PROCESS_EXITED_WITH_NON_ZERO_CODE: "TASK_PROCESS_EXITED_WITH_NON_ZERO_CODE",
8989
TASK_PROCESS_SIGKILL_TIMEOUT: "TASK_PROCESS_SIGKILL_TIMEOUT",
90+
TASK_PROCESS_OOM_KILLED: "TASK_PROCESS_OOM_KILLED",
91+
TASK_PROCESS_MAYBE_OOM_KILLED: "TASK_PROCESS_MAYBE_OOM_KILLED",
9092
TASK_RUN_CANCELLED: "TASK_RUN_CANCELLED",
9193
TASK_OUTPUT_ERROR: "TASK_OUTPUT_ERROR",
9294
HANDLE_ERROR_ERROR: "HANDLE_ERROR_ERROR",
@@ -107,6 +109,8 @@ export const TaskRunInternalError = z.object({
107109
"TASK_EXECUTION_ABORTED",
108110
"TASK_PROCESS_EXITED_WITH_NON_ZERO_CODE",
109111
"TASK_PROCESS_SIGKILL_TIMEOUT",
112+
"TASK_PROCESS_OOM_KILLED",
113+
"TASK_PROCESS_MAYBE_OOM_KILLED",
110114
"TASK_RUN_CANCELLED",
111115
"TASK_OUTPUT_ERROR",
112116
"HANDLE_ERROR_ERROR",

0 commit comments

Comments
 (0)