Skip to content

Align JSON error and event schemas with output conventions - #8800

Merged
gonzaloriestra merged 3 commits into
mainfrom
gonzalo/json-error-event-conventions
Oct 6, 2026
Merged

gonzaloriestra merged 3 commits into
mainfrom
gonzalo/json-error-event-conventions

Conversation

@gonzaloriestra

@gonzaloriestra gonzaloriestra commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

WHY are these changes introduced?

Shared diagnostic and progress events emit fractional timestamps and accept timezone offsets, although json-output.md requires whole-second UTC instants. Progress counts also accept fractions, and fatal errors cannot expose stable codes.

WHAT is this pull request doing?

Reuse the timestamp validator and formatter for events and bulk-operation results, truncate fractional seconds without rounding, and require nonnegative integer progress counts. Add optional nonempty stable codes to fatal errors while preserving native API details. These event and error outputs have not been released, so no changeset is needed.

How to manually test your changes?

pnpm shopify version --json-schema
pnpm shopify upgrade --json

Checklist

  • I've considered possible cross-platform impacts (Mac, Linux, Windows)
  • I've considered possible documentation changes
  • I've considered analytics changes to measure impact
  • The change is user-facing — I've identified the correct bump type and added a changeset.

@github-actions github-actions Bot added Area: @shopify/cli @shopify/cli package issues no-changelog This PR doesn't include a changeset entry. Is an internal only change not relevant to end users. and removed Area: @shopify/cli @shopify/cli package issues labels Oct 6, 2026
@github-actions

github-actions Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

Differences in type declarations

We detected differences in the type declarations generated by Typescript for this branch compared to the baseline ('main' branch). Please, review them to ensure they are backward-compatible. Here are some important things to keep in mind:

  • Some seemingly private modules might be re-exported through public modules.
  • If the branch is behind main you might see odd diffs, rebase main into this branch.

New type declarations

packages/cli-kit/dist/public/common/json-output-schema.d.ts
import { z } from 'zod';
/** UTC instants in CLI-owned JSON use whole seconds and the Z timezone marker. */
export declare const jsonOutputTimestampSchema: z.ZodString;
/**
 * Formats an instant for CLI-owned JSON, truncating fractional seconds without rounding.
 *
 * @param date - The instant to format.
 * @returns A UTC ISO 8601 timestamp with whole seconds and the Z timezone marker.
 */
export declare function formatJsonOutputTimestamp(date: Date): string;

Existing type declarations

packages/cli-kit/dist/private/node/json-error.d.ts
@@ -9,6 +9,7 @@ interface FatalErrorLike {
     command?: unknown;
     args?: unknown;
     details?: unknown;
+    code?: unknown;
 }
 /**
  * Writes the public JSON representation of a fatal error to stdout.
packages/cli-kit/dist/public/common/command-events.d.ts
@@ -120,6 +120,6 @@ export interface CommandEventChannelOptions<TEvent extends CommandEvent> {
  * Adapters validate events at their output boundary; the channel preserves domain-specific event fields.
  *
  * @param options - The event sink and clock used by the channel.
- * @returns A channel that adds an ISO timestamp before synchronously delivering each event.
+ * @returns A channel that adds a whole-second UTC timestamp before synchronously delivering each event.
  */
 export declare function createCommandEventChannel<TEvent extends CommandEvent = CommandEvent>(options?: CommandEventChannelOptions<TEvent>): CommandEventChannel<TEvent>;
\ No newline at end of file
packages/cli-kit/dist/public/node/json-output-schema.d.ts
@@ -1,8 +1,6 @@
-import { zod } from './schema.js';
 import { zodToJsonSchema } from 'zod-to-json-schema';
 import type { ZodTypeAny, z } from 'zod';
-/** UTC instants in CLI-owned results use whole seconds and the Z timezone marker. */
-export declare const jsonOutputTimestampSchema: zod.ZodString;
+export { formatJsonOutputTimestamp, jsonOutputTimestampSchema } from '../common/json-output-schema.js';
 interface JsonOutputSchemaDefinition<TSchema extends ZodTypeAny = ZodTypeAny> {
     readonly name: string;
     readonly schema: TSchema;
@@ -25,5 +23,4 @@ interface DefineJsonOutputSchemaOptions<TSchema extends ZodTypeAny> {
  * @param options - The root schema name, its Zod schema, and any named nested schemas.
  * @returns The complete JSON output contract.
  */
-export declare function defineJsonOutputSchema<TSchema extends ZodTypeAny>(options: DefineJsonOutputSchemaOptions<TSchema>): JsonOutputSchema<TSchema>;
-export {};
\ No newline at end of file
+export declare function defineJsonOutputSchema<TSchema extends ZodTypeAny>(options: DefineJsonOutputSchemaOptions<TSchema>): JsonOutputSchema<TSchema>;
\ No newline at end of file
packages/cli-kit/dist/public/node/error/index.d.ts
@@ -18,6 +18,8 @@ export declare abstract class FatalError extends Error {
     nextSteps?: TokenItem<InlineToken>[];
     formattedMessage?: TokenItem;
     customSections?: AlertCustomSection[];
+    /** A stable code for JSON consumers to identify this error, included only when known. */
+    code?: string;
     /** Selected JSON-serializable data to include in JSON errors. Never attach the raw error or request. */
     details?: unknown;
     skipOclifErrorHandling: boolean;
packages/cli-kit/dist/public/node/error/schema.d.ts
@@ -11,6 +11,7 @@ export declare const JsonErrorCustomSectionSchema: zod.ZodObject<{
 }>;
 export declare const JsonAbortErrorSchema: zod.ZodObject<{
     message: zod.ZodString;
+    code: zod.ZodOptional<zod.ZodString>;
     tryMessage: zod.ZodOptional<zod.ZodString>;
     nextSteps: zod.ZodOptional<zod.ZodArray<zod.ZodString, "many">>;
     customSections: zod.ZodOptional<zod.ZodArray<zod.ZodObject<{
@@ -28,6 +29,7 @@ export declare const JsonAbortErrorSchema: zod.ZodObject<{
 }, "strict", zod.ZodTypeAny, {
     type: "abort";
     message: string;
+    code?: string | undefined;
     nextSteps?: string[] | undefined;
     customSections?: {
         body: string | string[][];
@@ -38,6 +40,7 @@ export declare const JsonAbortErrorSchema: zod.ZodObject<{
 }, {
     type: "abort";
     message: string;
+    code?: string | undefined;
     nextSteps?: string[] | undefined;
     customSections?: {
         body: string | string[][];
@@ -49,6 +52,7 @@ export declare const JsonAbortErrorSchema: zod.ZodObject<{
 export declare const JsonBugErrorSchema: zod.ZodObject<{
     stack: zod.ZodOptional<zod.ZodString>;
     message: zod.ZodString;
+    code: zod.ZodOptional<zod.ZodString>;
     tryMessage: zod.ZodOptional<zod.ZodString>;
     nextSteps: zod.ZodOptional<zod.ZodArray<zod.ZodString, "many">>;
     customSections: zod.ZodOptional<zod.ZodArray<zod.ZodObject<{
@@ -66,6 +70,7 @@ export declare const JsonBugErrorSchema: zod.ZodObject<{
 }, "strict", zod.ZodTypeAny, {
     type: "bug";
     message: string;
+    code?: string | undefined;
     stack?: string | undefined;
     nextSteps?: string[] | undefined;
     customSections?: {
@@ -77,6 +82,7 @@ export declare const JsonBugErrorSchema: zod.ZodObject<{
 }, {
     type: "bug";
     message: string;
+    code?: string | undefined;
     stack?: string | undefined;
     nextSteps?: string[] | undefined;
     customSections?: {
@@ -90,6 +96,7 @@ export declare const JsonExternalErrorSchema: zod.ZodObject<{
     command: zod.ZodString;
     args: zod.ZodArray<zod.ZodString, "many">;
     message: zod.ZodString;
+    code: zod.ZodOptional<zod.ZodString>;
     tryMessage: zod.ZodOptional<zod.ZodString>;
     nextSteps: zod.ZodOptional<zod.ZodArray<zod.ZodString, "many">>;
     customSections: zod.ZodOptional<zod.ZodArray<zod.ZodObject<{
@@ -109,6 +116,7 @@ export declare const JsonExternalErrorSchema: zod.ZodObject<{
     message: string;
     command: string;
     args: string[];
+    code?: string | undefined;
     nextSteps?: string[] | undefined;
     customSections?: {
         body: string | string[][];
@@ -121,6 +129,7 @@ export declare const JsonExternalErrorSchema: zod.ZodObject<{
     message: string;
     command: string;
     args: string[];
+    code?: string | undefined;
     nextSteps?: string[] | undefined;
     customSections?: {
         body: string | string[][];
@@ -131,6 +140,7 @@ export declare const JsonExternalErrorSchema: zod.ZodObject<{
 }>;
 export declare const JsonErrorSchema: zod.ZodUnion<[zod.ZodObject<{
     message: zod.ZodString;
+    code: zod.ZodOptional<zod.ZodString>;
     tryMessage: zod.ZodOptional<zod.ZodString>;
     nextSteps: zod.ZodOptional<zod.ZodArray<zod.ZodString, "many">>;
     customSections: zod.ZodOptional<zod.ZodArray<zod.ZodObject<{
@@ -148,6 +158,7 @@ export declare const JsonErrorSchema: zod.ZodUnion<[zod.ZodObject<{
 }, "strict", zod.ZodTypeAny, {
     type: "abort";
     message: string;
+    code?: string | undefined;
     nextSteps?: string[] | undefined;
     customSections?: {
         body: string | string[][];
@@ -158,6 +169,7 @@ export declare const JsonErrorSchema: zod.ZodUnion<[zod.ZodObject<{
 }, {
     type: "abort";
     message: string;
+    code?: string | undefined;
     nextSteps?: string[] | undefined;
     customSections?: {
         body: string | string[][];
@@ -168,6 +180,7 @@ export declare const JsonErrorSchema: zod.ZodUnion<[zod.ZodObject<{
 }>, zod.ZodObject<{
     stack: zod.ZodOptional<zod.ZodString>;
     message: zod.ZodString;
+    code: zod.ZodOptional<zod.ZodString>;
     tryMessage: zod.ZodOptional<zod.ZodString>;
     nextSteps: zod.ZodOptional<zod.ZodArray<zod.ZodString, "many">>;
     customSections: zod.ZodOptional<zod.ZodArray<zod.ZodObject<{
@@ -185,6 +198,7 @@ export declare const JsonErrorSchema: zod.ZodUnion<[zod.ZodObject<{
 }, "strict", zod.ZodTypeAny, {
     type: "bug";
     message: string;
+    code?: string | undefined;
     stack?: string | undefined;
     nextSteps?: string[] | undefined;
     customSections?: {
@@ -196,6 +210,7 @@ export declare const JsonErrorSchema: zod.ZodUnion<[zod.ZodObject<{
 }, {
     type: "bug";
     message: string;
+    code?: string | undefined;
     stack?: string | undefined;
     nextSteps?: string[] | undefined;
     customSections?: {
@@ -208,6 +223,7 @@ export declare const JsonErrorSchema: zod.ZodUnion<[zod.ZodObject<{
     command: zod.ZodString;
     args: zod.ZodArray<zod.ZodString, "many">;
     message: zod.ZodString;
+    code: zod.ZodOptional<zod.ZodString>;
     tryMessage: zod.ZodOptional<zod.ZodString>;
     nextSteps: zod.ZodOptional<zod.ZodArray<zod.ZodString, "many">>;
     customSections: zod.ZodOptional<zod.ZodArray<zod.ZodObject<{
@@ -227,6 +243,7 @@ export declare const JsonErrorSchema: zod.ZodUnion<[zod.ZodObject<{
     message: string;
     command: string;
     args: string[];
+    code?: string | undefined;
     nextSteps?: string[] | undefined;
     customSections?: {
         body: string | string[][];
@@ -239,6 +256,7 @@ export declare const JsonErrorSchema: zod.ZodUnion<[zod.ZodObject<{
     message: string;
     command: string;
     args: string[];
+    code?: string | undefined;
     nextSteps?: string[] | undefined;
     customSections?: {
         body: string | string[][];
@@ -250,6 +268,7 @@ export declare const JsonErrorSchema: zod.ZodUnion<[zod.ZodObject<{
 export declare const jsonErrorOutputSchema: import("../json-output-schema.js").JsonOutputSchema<zod.ZodObject<{
     error: zod.ZodUnion<[zod.ZodObject<{
         message: zod.ZodString;
+        code: zod.ZodOptional<zod.ZodString>;
         tryMessage: zod.ZodOptional<zod.ZodString>;
         nextSteps: zod.ZodOptional<zod.ZodArray<zod.ZodString, "many">>;
         customSections: zod.ZodOptional<zod.ZodArray<zod.ZodObject<{
@@ -267,6 +286,7 @@ export declare const jsonErrorOutputSchema: import("../json-output-schema.js").J
     }, "strict", zod.ZodTypeAny, {
         type: "abort";
         message: string;
+        code?: string | undefined;
         nextSteps?: string[] | undefined;
         customSections?: {
             body: string | string[][];
@@ -277,6 +297,7 @@ export declare const jsonErrorOutputSchema: import("../json-output-schema.js").J
     }, {
         type: "abort";
         message: string;
+        code?: string | undefined;
         nextSteps?: string[] | undefined;
         customSections?: {
             body: string | string[][];
@@ -287,6 +308,7 @@ export declare const jsonErrorOutputSchema: import("../json-output-schema.js").J
     }>, zod.ZodObject<{
         stack: zod.ZodOptional<zod.ZodString>;
         message: zod.ZodString;
+        code: zod.ZodOptional<zod.ZodString>;
         tryMessage: zod.ZodOptional<zod.ZodString>;
         nextSteps: zod.ZodOptional<zod.ZodArray<zod.ZodString, "many">>;
         customSections: zod.ZodOptional<zod.ZodArray<zod.ZodObject<{
@@ -304,6 +326,7 @@ export declare const jsonErrorOutputSchema: import("../json-output-schema.js").J
     }, "strict", zod.ZodTypeAny, {
         type: "bug";
         message: string;
+        code?: string | undefined;
         stack?: string | undefined;
         nextSteps?: string[] | undefined;
         customSections?: {
@@ -315,6 +338,7 @@ export declare const jsonErrorOutputSchema: import("../json-output-schema.js").J
     }, {
         type: "bug";
         message: string;
+        code?: string | undefined;
         stack?: string | undefined;
         nextSteps?: string[] | undefined;
         customSections?: {
@@ -327,6 +351,7 @@ export declare const jsonErrorOutputSchema: import("../json-output-schema.js").J
         command: zod.ZodString;
         args: zod.ZodArray<zod.ZodString, "many">;
         message: zod.ZodString;
+        code: zod.ZodOptional<zod.ZodString>;
         tryMessage: zod.ZodOptional<zod.ZodString>;
         nextSteps: zod.ZodOptional<zod.ZodArray<zod.ZodString, "many">>;
         customSections: zod.ZodOptional<zod.ZodArray<zod.ZodObject<{
@@ -346,6 +371,7 @@ export declare const jsonErrorOutputSchema: import("../json-output-schema.js").J
         message: string;
         command: string;
         args: string[];
+        code?: string | undefined;
         nextSteps?: string[] | undefined;
         customSections?: {
             body: string | string[][];
@@ -358,6 +384,7 @@ export declare const jsonErrorOutputSchema: import("../json-output-schema.js").J
         message: string;
         command: string;
         args: string[];
+        code?: string | undefined;
         nextSteps?: string[] | undefined;
         customSections?: {
             body: string | string[][];
@@ -370,6 +397,7 @@ export declare const jsonErrorOutputSchema: import("../json-output-schema.js").J
     error: {
         type: "abort";
         message: string;
+        code?: string | undefined;
         nextSteps?: string[] | undefined;
         customSections?: {
             body: string | string[][];
@@ -380,6 +408,7 @@ export declare const jsonErrorOutputSchema: import("../json-output-schema.js").J
     } | {
         type: "bug";
         message: string;
+        code?: string | undefined;
         stack?: string | undefined;
         nextSteps?: string[] | undefined;
         customSections?: {
@@ -393,6 +422,7 @@ export declare const jsonErrorOutputSchema: import("../json-output-schema.js").J
         message: string;
         command: string;
         args: string[];
+        code?: string | undefined;
         nextSteps?: string[] | undefined;
         customSections?: {
             body: string | string[][];
@@ -405,6 +435,7 @@ export declare const jsonErrorOutputSchema: import("../json-output-schema.js").J
     error: {
         type: "abort";
         message: string;
+        code?: string | undefined;
         nextSteps?: string[] | undefined;
         customSections?: {
             body: string | string[][];
@@ -415,6 +446,7 @@ export declare const jsonErrorOutputSchema: import("../json-output-schema.js").J
     } | {
         type: "bug";
         message: string;
+        code?: string | undefined;
         stack?: string | undefined;
         nextSteps?: string[] | undefined;
         customSections?: {
@@ -428,6 +460,7 @@ export declare const jsonErrorOutputSchema: import("../json-output-schema.js").J
         message: string;
         command: string;
         args: string[];
+        code?: string | undefined;
         nextSteps?: string[] | undefined;
         customSections?: {
             body: string | string[][];

@gonzaloriestra
gonzaloriestra marked this pull request as ready for review October 6, 2026 14:48
@gonzaloriestra
gonzaloriestra requested a review from a team as a code owner October 6, 2026 14:48
@gonzaloriestra
gonzaloriestra added this pull request to the merge queue Oct 6, 2026
Merged via the queue into main with commit ea92e89 Oct 6, 2026
54 of 55 checks passed
@gonzaloriestra
gonzaloriestra deleted the gonzalo/json-error-event-conventions branch October 6, 2026 15:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

no-changelog This PR doesn't include a changeset entry. Is an internal only change not relevant to end users.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants