Skip to content
This repository was archived by the owner on Oct 22, 2025. It is now read-only.

Commit 41e080c

Browse files
committed
chore: standardize error logging with stringifyError (#857)
1 parent 6eddf69 commit 41e080c

File tree

8 files changed

+209
-26
lines changed

8 files changed

+209
-26
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
"packages/components/*",
1010
"packages/misc/*",
1111
"packages/frameworks/*",
12-
"examples/*"
12+
"examples/*",
13+
"templates/*"
1314
],
1415
"scripts": {
1516
"start": "npx turbo watch build",

packages/actor-core-cli/src/utils/platforms.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ const PLATFORMS = {
101101
...pkgJson,
102102
scripts: {
103103
...pkgJson.scripts,
104-
deploy: "actor-core deploy rivet actors/app.ts",
104+
deploy: "npx @actor-core/cli deploy rivet actors/app.ts",
105105
},
106106
devDependencies: {
107107
"@actor-core/cli": version,
@@ -256,9 +256,12 @@ serve(app);
256256
},
257257
},
258258
noop: {
259-
modify: ({ files }) => {
260-
// Do nothing
261-
return { files };
259+
modify: ({ files, pkgJson }) => {
260+
files["package.json"] = stringifyJson(pkgJson);
261+
262+
return {
263+
files,
264+
};
262265
},
263266
},
264267
} satisfies Record<string, PlatformConfig>;

packages/actor-core/src/actor/instance.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import type { PersistedConn } from "./connection";
22
import type { Logger } from "@/common//log";
3-
import { type ActorTags, isJsonSerializable } from "@/common//utils";
3+
import { type ActorTags, isJsonSerializable, stringifyError } from "@/common//utils";
44
import onChange from "on-change";
55
import type { ActorConfig } from "./config";
66
import { Conn, type ConnId } from "./connection";
@@ -346,7 +346,7 @@ export class ActorInstance<S, CP, CS, V> {
346346
this.#config.onStateChange(this.actorContext, this.#persistRaw.s);
347347
} catch (error) {
348348
logger().error("error in `_onStateChange`", {
349-
error: `${error}`,
349+
error: stringifyError(error),
350350
});
351351
}
352352
}
@@ -473,13 +473,13 @@ export class ActorInstance<S, CP, CS, V> {
473473
// Handle promise but don't await it to prevent blocking
474474
result.catch((error) => {
475475
logger().error("error in `onDisconnect`", {
476-
error: `${error}`,
476+
error: stringifyError(error),
477477
});
478478
});
479479
}
480480
} catch (error) {
481481
logger().error("error in `onDisconnect`", {
482-
error: `${error}`,
482+
error: stringifyError(error),
483483
});
484484
}
485485
}
@@ -591,7 +591,7 @@ export class ActorInstance<S, CP, CS, V> {
591591
}
592592
} catch (error) {
593593
logger().error("error in `onConnect`", {
594-
error: `${error}`,
594+
error: stringifyError(error),
595595
});
596596
conn?.disconnect("`onConnect` failed");
597597
}
@@ -768,7 +768,7 @@ export class ActorInstance<S, CP, CS, V> {
768768
}
769769
} catch (error) {
770770
logger().error("error in `onBeforeRpcResponse`", {
771-
error: `${error}`,
771+
error: stringifyError(error),
772772
});
773773
}
774774
}
@@ -908,7 +908,7 @@ export class ActorInstance<S, CP, CS, V> {
908908
})
909909
.catch((error) => {
910910
logger().error("background promise failed", {
911-
error: `${error}`,
911+
error: stringifyError(error),
912912
});
913913
});
914914
this.#backgroundPromises.push(nonfailablePromise);

packages/actor-core/src/actor/router.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { type SSEStreamingApi, streamSSE } from "hono/streaming";
1111
import { cors } from "hono/cors";
1212
import { assertUnreachable } from "./utils";
1313
import { handleRouteError, handleRouteNotFound } from "@/common/router";
14-
import { deconstructError } from "@/common/utils";
14+
import { deconstructError, stringifyError } from "@/common/utils";
1515
import type { DriverConfig } from "@/driver-helpers/config";
1616
import type { AppConfig } from "@/app/config";
1717
import {
@@ -186,7 +186,9 @@ export function createActorRouter(
186186

187187
// Actors don't need to know about this, since it's abstracted
188188
// away
189-
logger().warn("websocket error", { error: `${error}` });
189+
logger().warn("websocket error", {
190+
error: stringifyError(error),
191+
});
190192
} catch (error) {
191193
deconstructError(error, logger(), { wsEvent: "error" });
192194
}
@@ -238,7 +240,7 @@ export function createActorRouter(
238240
async (error) => {
239241
// Actors don't need to know about this, since it's abstracted
240242
// away
241-
logger().warn("sse error", { error: `${error}` });
243+
logger().warn("sse error", { error: stringifyError(error) });
242244
},
243245
);
244246
});
@@ -407,7 +409,7 @@ function getRequestConnParams(
407409
return typeof paramsStr === "string" ? JSON.parse(paramsStr) : undefined;
408410
} catch (error) {
409411
logger().warn("malformed connection parameters", {
410-
error: `${error}`,
412+
error: stringifyError(error),
411413
});
412414
throw new errors.MalformedConnParams(error);
413415
}

packages/actor-core/src/actor/schedule.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { AnyActorInstance } from "./instance";
22
import type { ActorDriver } from "./driver";
33
import { KEYS } from "./keys";
44
import { logger } from "./log";
5+
import { stringifyError } from "@/common/utils";
56

67
interface ScheduleState {
78
// Sorted by timestamp asc
@@ -151,15 +152,15 @@ export class Schedule {
151152
} catch (err) {
152153
logger().error("failed to run scheduled event", {
153154
fn: event.fn,
154-
error: `${err}`,
155+
error: stringifyError(err),
155156
});
156157

157158
// Write internal error
158159
await this.#driver.kvPut(
159160
this.#actor.id,
160161
KEYS.SCHEDULE.alarmError(event.fn),
161162
{
162-
error: `${err}`,
163+
error: stringifyError(err),
163164
timestamp: now,
164165
},
165166
);

packages/actor-core/src/client/handle.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import type { Encoding } from "@/actor/protocol/serde";
33
import type * as wsToClient from "@/actor/protocol/message/to-client";
44
import type * as wsToServer from "@/actor/protocol/message/to-server";
55
import { MAX_CONN_PARAMS_SIZE } from "@/common/network";
6-
import { assertUnreachable } from "@/common/utils";
6+
import { assertUnreachable, stringifyError } from "@/common/utils";
77
import * as cbor from "cbor-x";
88
import * as errors from "./errors";
99
import { logger } from "./log";
@@ -186,7 +186,7 @@ enc
186186
onFailedAttempt: (error) => {
187187
logger().warn("failed to reconnect", {
188188
attempt: error.attemptNumber,
189-
error: `${error}`,
189+
error: stringifyError(error),
190190
});
191191
},
192192

packages/actor-core/src/common/utils.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,23 @@ export function deconstructError(
158158

159159
return { statusCode, code, message, metadata };
160160
}
161+
162+
export function stringifyError(error: unknown): string {
163+
if (error instanceof Error) {
164+
if (process.env._ACTOR_CORE_ERROR_STACK === "1") {
165+
return `${error.name}: ${error.message}${error.stack ? `\n${error.stack}` : ""}`;
166+
} else {
167+
return `${error.name}: ${error.message}`;
168+
}
169+
} else if (typeof error === "string") {
170+
return error;
171+
} else if (typeof error === "object" && error !== null) {
172+
try {
173+
return `${JSON.stringify(error)}`;
174+
} catch {
175+
return "[cannot stringify error]";
176+
}
177+
} else {
178+
return `Unknown error: ${String(error)}`;
179+
}
180+
}

0 commit comments

Comments
 (0)