Skip to main content

error-reporting

Error handling and logging policy for @shopify/hydrogen: when to throw, when to log through the logging contract, when to expose reactive state, and how tests assert failures. Always use when developing or reviewing runtime logic for the @shopify/hydrogen library.

来源信息

仓库
Shopify/hydrogen
最近来源活动
2026年9月28日 11:19
检测到的 SKILL.md 语言
英语
星标
2,142
分支
447

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
error-reporting
description
Error handling and logging policy for @shopify/hydrogen: when to throw, when to log through the logging contract, when to expose reactive state, and how tests assert failures. Always use when developing or reviewing runtime logic for the @shopify/hydrogen library.
# Error Reporting Policy How `@shopify/hydrogen` handles runtime failures: when to throw, when to log, when to expose reactive state, and how logs are formatted, configured, and tested. Apply this policy to any new or changed runtime logic in `packages/hydrogen/src`. ## Taxonomy Pick the mechanism from the failure class. Never double-report (throw AND log the same failure). | Failure class | Mechanism | Examples | | --- | --- | --- | | Programming errors | Throw a typed error synchronously. | Bad arguments, invariant violations. | | Request-scoped failures with a caller | Throw a typed error; the caller decides retry/render. | `StorefrontApiError`, `CustomerAccountApiError`, `CartActionError`, `CartNetworkError`. | | Server handlers with internal recovery | Catch failures, log via the scoped logger, return a structured error `Response`. | Cart server handler catches a network failure and returns `500` with a JSON error body. | | Background browser failures | Scoped logger at `error` level. | Runtime script loads, background cart loads, analytics publish failures. | | Misuse / degradation | Scoped logger at `warn` level. | Mock shop detected, analytics destination misconfigured, deprecated option passed. | | Buyer-visible user errors | Reactive state only — never logged. | Cart `userErrors` surfaced to the UI; the user corrects and retries. | ## Logger contract ### Internal call convention `getLogger` is internal — not part of the public package API. ```ts import { getLogger } from "../logging"; // relative import within src/ const log = getLogger("cart"); log.error("cart initial load failed", { error }); ``` - `getLogger(scope)` returns a lazily-resolved scoped logger. Prefer one module-level `const log` per file when the scope is static. Use stable subsystem scopes; proxy descriptors provide dynamic scopes. - Messages are unprefixed, lowercase-leaning, and without trailing colons; the sink owns formatting. - `context.error` becomes a separate console argument; other context keys become a trailing object. - Never call `console.*` directly in runtime files under `packages/hydrogen/src` — the `no-console` lint rule enforces this. Sanctioned runtime exceptions: the built-in sink in `src/core/logging/logging.ts`, the serialized consent bootstrap in `src/core/shopify-scripts/consent-script.ts`, and the CLI. Tests may spy on or mock `console` for the exceptions listed below. ### `HydrogenLogger` A minimal structural interface with six level methods: ```ts interface HydrogenLogger { trace: (message: string, context?: LogContext) => void; debug: (message: string, context?: LogContext) => void; info: (message: string, context?: LogContext) => void; warn: (message: string, context?: LogContext) => void; error: (message: string, context?: LogContext) => void; fatal: (message: string, context?: LogContext) => void; } ``` `LogContext` is `{ scope?: string; error?: unknown; [key: string]: unknown }`. ### `configureLogging` ```ts import { configureLogging } from "@shopify/hydrogen"; const logger = { trace: console.debug, debug: console.debug, info: console.info, warn: console.warn, error: console.error, fatal: console.error, }; configureLogging({ logger, level: "warn" }); ``` - Global, called once at startup (app entry on the browser, module init on the server). - `logger` — any `HydrogenLogger`; defaults to the built-in console sink. - `level` — minimum severity forwarded; defaults to `"info"`. - Last-call-wins: reconfiguring applies the new options. ### Default console sink Formats entries as `[hydrogen:<level>:<scope>] <message>`, followed by `context.error` (if present) and a trailing object of remaining context fields. ## Serialized inline scripts — documented exception Inline/CDN scripts that Hydrogen serializes into HTML are compiled to strings via `import … with { type: "script" }` chains. They never see the app bundle's global state, so `configureLogging` cannot reach them. The analytics bootstrap path and its bus/destination-manager modules write to `console` with the standard `[hydrogen:<level>:<scope>]` prefix via the `consoleLogger` sink — when writing code in a serialized-script import chain that shares modules with the app bundle, use `consoleLogger` directly with an explicit `{ scope }` instead of `getLogger`. Serialized-only leaf modules (the consent bootstrap) hardcode the prefix in a plain `console.*` call instead, so the logging module is not inlined into every HTML response. ## Non-goals - Per-request child loggers / request correlation. Scopes are per-subsystem, not per-request. ## Test expectations - Failure paths inject a test logger instead of mocking `console`: `configureLogging({ logger })` with six `vi.fn()` methods, `configureLogging({})` in `afterEach` to restore the defaults. Assert `(message, { scope, ...context })` — no prefix strings. - Exceptions that still spy `console`: serialized inline-script import chains (analytics bus/destination-manager, consent) write to `console` directly, and `logging.test.ts` verifies the sink's own `[hydrogen:<level>:<scope>]` formatting. - The `no-console` lint rule enforces the policy: the sanctioned `console` call sites are `src/core/logging/logging.ts` and the serialized consent bootstrap `src/core/shopify-scripts/consent-script.ts`, each carrying an inline `oxlint-disable-next-line no-console`. CLI and test files are exempt.
在 GitHub 查看