@mastra/server 1.60.0 → 1.60.1-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # @mastra/server
2
2
 
3
+ ## 1.60.1-alpha.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Fixed concurrent resume() calls on the same suspended workflow run executing downstream steps more than once. A resume now atomically claims the run before executing anything, so only one caller continues a given suspension. Losing callers throw WORKFLOW_RESUME_ALREADY_CLAIMED without running any steps. Fixes #20443 ([#21725](https://github.com/mastra-ai/mastra/pull/21725))
8
+
9
+ - Workflow state updates now support an optional expectedStatus guard, so a status change is only applied when the stored run is in an expected state. This is what makes concurrent workflow resumes safe. ([#21725](https://github.com/mastra-ai/mastra/pull/21725))
10
+
11
+ - Resume conflicts now return 409 Conflict. When a suspended workflow run has already been resumed by another caller, the resume endpoints respond with 409 instead of a generic error. ([#21725](https://github.com/mastra-ai/mastra/pull/21725))
12
+
13
+ - Updated dependencies [[`88d14ca`](https://github.com/mastra-ai/mastra/commit/88d14cac008582a618fecc3d5c7fd3bdf4f6ddc3), [`84a5b69`](https://github.com/mastra-ai/mastra/commit/84a5b699f84d6bae0a34efe5a970d891090b9f41), [`84a5b69`](https://github.com/mastra-ai/mastra/commit/84a5b699f84d6bae0a34efe5a970d891090b9f41), [`84a5b69`](https://github.com/mastra-ai/mastra/commit/84a5b699f84d6bae0a34efe5a970d891090b9f41), [`038b7b4`](https://github.com/mastra-ai/mastra/commit/038b7b405cb4ac25ab3f3031334111b1f87ac112), [`4132d61`](https://github.com/mastra-ai/mastra/commit/4132d61f8367077120ee9e6420d3224dffd93c93)]:
14
+ - @mastra/core@1.60.1-alpha.0
15
+
3
16
  ## 1.60.0
4
17
 
5
18
  ### Minor Changes
@@ -3,7 +3,7 @@ name: mastra-server
3
3
  description: Documentation for @mastra/server. Use when working with @mastra/server APIs, configuration, or implementation.
4
4
  metadata:
5
5
  package: "@mastra/server"
6
- version: "1.60.0"
6
+ version: "1.60.1-alpha.0"
7
7
  ---
8
8
 
9
9
  ## When to use
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.60.0",
2
+ "version": "1.60.1-alpha.0",
3
3
  "package": "@mastra/server",
4
4
  "exports": {},
5
5
  "modules": {}
@@ -20,6 +20,10 @@ const WORKFLOW_SCHEMA_VALIDATION_FAILED_CODE = "WORKFLOW_SCHEMA_VALIDATION_FAILE
20
20
  function isWorkflowSchemaValidationError(error) {
21
21
  return error instanceof Error && error.id === WORKFLOW_SCHEMA_VALIDATION_FAILED_CODE;
22
22
  }
23
+ const WORKFLOW_RESUME_ALREADY_CLAIMED_CODE = "WORKFLOW_RESUME_ALREADY_CLAIMED";
24
+ function isWorkflowResumeAlreadyClaimedError(error) {
25
+ return error instanceof Error && error.id === WORKFLOW_RESUME_ALREADY_CLAIMED_CODE;
26
+ }
23
27
  /**
24
28
  * Structural check for ZodError instances.
25
29
  *
@@ -65,6 +69,11 @@ function handleError(error, defaultMessage) {
65
69
  cause: error
66
70
  });
67
71
  }
72
+ if (isWorkflowResumeAlreadyClaimedError(error)) throw new require_http_exception.HTTPException(409, {
73
+ message: error.message,
74
+ stack: error.stack,
75
+ cause: error
76
+ });
68
77
  if (isWorkflowSchemaValidationError(error)) throw new require_http_exception.HTTPException(400, {
69
78
  message: error.message,
70
79
  stack: error.stack,
@@ -1 +1 @@
1
- {"version":3,"file":"error.cjs","names":["HTTPException"],"sources":["../../../src/server/handlers/error.ts"],"sourcesContent":["import type { ZodError } from 'zod';\n\nimport { HTTPException } from '../http-exception';\nimport type { StatusCode } from '../http-exception';\nimport type { ApiError } from '../types';\n\n/**\n * Duck-typed interface for ZodError-like objects.\n * Note: Zod v4 uses PropertyKey[] (string | number | symbol) for path.\n */\nexport interface ZodErrorLike {\n issues: Array<{\n path: PropertyKey[];\n message: string;\n }>;\n}\n\n/**\n * Recognition for `ModelNotAllowedError` from `@mastra/core/agent-builder/ee`.\n *\n * Inlined as a duck check rather than imported so that `handleError` (wired\n * into every route) does not force a load-time dependency on the\n * `@mastra/core/agent-builder/ee` subpath. That subpath only ships in\n * `@mastra/core >= 1.34.0`; deploys whose bundled `@mastra/server` resolves\n * against an older core would otherwise crash at startup with\n * `ERR_MODULE_NOT_FOUND` on `@mastra/core/dist/agent-builder/ee/index.js`.\n */\nconst MODEL_NOT_ALLOWED_CODE = 'MODEL_NOT_ALLOWED';\n\ninterface ModelNotAllowedErrorLike extends Error {\n code: typeof MODEL_NOT_ALLOWED_CODE;\n allowed?: unknown;\n attempted?: unknown;\n offendingLabel?: string;\n}\n\nfunction isModelNotAllowedError(error: unknown): error is ModelNotAllowedErrorLike {\n return error instanceof Error && (error as { code?: unknown }).code === MODEL_NOT_ALLOWED_CODE;\n}\n\nconst WORKFLOW_SCHEMA_VALIDATION_FAILED_CODE = 'WORKFLOW_SCHEMA_VALIDATION_FAILED';\n\nfunction isWorkflowSchemaValidationError(error: unknown): error is Error {\n return error instanceof Error && (error as { id?: unknown }).id === WORKFLOW_SCHEMA_VALIDATION_FAILED_CODE;\n}\n\n/**\n * Structural check for ZodError instances.\n *\n * Avoids `instanceof ZodError` because consumers can resolve `'zod'` to a\n * different package instance (e.g. `zod@^3`) than the one a server adapter is\n * bundled with (`zod@^4`). In that case `instanceof` is false and validation\n * errors fall through to a generic response that drops field-path information.\n *\n * See https://github.com/mastra-ai/mastra/issues/17167.\n */\nexport function isZodError(error: unknown): error is ZodError<any> {\n return (\n !!error &&\n typeof error === 'object' &&\n (error as { name?: unknown }).name === 'ZodError' &&\n Array.isArray((error as { issues?: unknown }).issues)\n );\n}\n\n/**\n * Formats a ZodError into a structured validation error response.\n * Returns an object with an error message and an array of field-specific issues.\n */\nexport function formatZodError(\n error: ZodErrorLike,\n context: string,\n): { error: string; issues: Array<{ field: string; message: string }> } {\n const issues = error.issues.map(e => ({\n field: e.path.length > 0 ? e.path.map(p => String(p)).join('.') : 'root',\n message: e.message,\n }));\n\n return {\n error: `Invalid ${context}`,\n issues,\n };\n}\n\n// Helper to handle errors consistently\nexport function handleError(error: unknown, defaultMessage: string): never {\n if (isModelNotAllowedError(error)) {\n const body = {\n error: {\n code: error.code,\n message: error.message,\n allowed: error.allowed,\n attempted: error.attempted,\n offendingLabel: error.offendingLabel,\n },\n };\n const res = new Response(JSON.stringify(body), {\n status: 422,\n headers: { 'content-type': 'application/json' },\n });\n throw new HTTPException(422, {\n res,\n message: error.message,\n cause: error,\n });\n }\n\n if (isWorkflowSchemaValidationError(error)) {\n throw new HTTPException(400, {\n message: error.message,\n stack: error.stack,\n cause: error,\n });\n }\n\n const apiError = error as ApiError;\n\n const apiErrorStatus = apiError.status || apiError.details?.status || 500;\n\n throw new HTTPException(apiErrorStatus as StatusCode, {\n message: apiError.message || defaultMessage,\n stack: apiError.stack,\n cause: apiError.cause,\n });\n}\n"],"mappings":";;;;;;;;;;;;;;AA2BA,MAAM,yBAAyB;AAS/B,SAAS,uBAAuB,OAAmD;CACjF,OAAO,iBAAiB,SAAU,MAA6B,SAAS;AAC1E;AAEA,MAAM,yCAAyC;AAE/C,SAAS,gCAAgC,OAAgC;CACvE,OAAO,iBAAiB,SAAU,MAA2B,OAAO;AACtE;;;;;;;;;;;AAYA,SAAgB,WAAW,OAAwC;CACjE,OACE,CAAC,CAAC,SACF,OAAO,UAAU,YAChB,MAA6B,SAAS,cACvC,MAAM,QAAS,MAA+B,MAAM;AAExD;;;;;AAMA,SAAgB,eACd,OACA,SACsE;CACtE,MAAM,SAAS,MAAM,OAAO,KAAI,OAAM;EACpC,OAAO,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,KAAI,MAAK,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI;EAClE,SAAS,EAAE;CACb,EAAE;CAEF,OAAO;EACL,OAAO,WAAW;EAClB;CACF;AACF;AAGA,SAAgB,YAAY,OAAgB,gBAA+B;CACzE,IAAI,uBAAuB,KAAK,GAAG;EACjC,MAAM,OAAO,EACX,OAAO;GACL,MAAM,MAAM;GACZ,SAAS,MAAM;GACf,SAAS,MAAM;GACf,WAAW,MAAM;GACjB,gBAAgB,MAAM;EACxB,EACF;EAKA,MAAM,IAAIA,uBAAAA,cAAc,KAAK;GAC3B,KAAA,IALc,SAAS,KAAK,UAAU,IAAI,GAAG;IAC7C,QAAQ;IACR,SAAS,EAAE,gBAAgB,mBAAmB;GAChD,CAEI;GACF,SAAS,MAAM;GACf,OAAO;EACT,CAAC;CACH;CAEA,IAAI,gCAAgC,KAAK,GACvC,MAAM,IAAIA,uBAAAA,cAAc,KAAK;EAC3B,SAAS,MAAM;EACf,OAAO,MAAM;EACb,OAAO;CACT,CAAC;CAGH,MAAM,WAAW;CAIjB,MAAM,IAAIA,uBAAAA,cAFa,SAAS,UAAU,SAAS,SAAS,UAAU,KAEhB;EACpD,SAAS,SAAS,WAAW;EAC7B,OAAO,SAAS;EAChB,OAAO,SAAS;CAClB,CAAC;AACH"}
1
+ {"version":3,"file":"error.cjs","names":["HTTPException"],"sources":["../../../src/server/handlers/error.ts"],"sourcesContent":["import type { ZodError } from 'zod';\n\nimport { HTTPException } from '../http-exception';\nimport type { StatusCode } from '../http-exception';\nimport type { ApiError } from '../types';\n\n/**\n * Duck-typed interface for ZodError-like objects.\n * Note: Zod v4 uses PropertyKey[] (string | number | symbol) for path.\n */\nexport interface ZodErrorLike {\n issues: Array<{\n path: PropertyKey[];\n message: string;\n }>;\n}\n\n/**\n * Recognition for `ModelNotAllowedError` from `@mastra/core/agent-builder/ee`.\n *\n * Inlined as a duck check rather than imported so that `handleError` (wired\n * into every route) does not force a load-time dependency on the\n * `@mastra/core/agent-builder/ee` subpath. That subpath only ships in\n * `@mastra/core >= 1.34.0`; deploys whose bundled `@mastra/server` resolves\n * against an older core would otherwise crash at startup with\n * `ERR_MODULE_NOT_FOUND` on `@mastra/core/dist/agent-builder/ee/index.js`.\n */\nconst MODEL_NOT_ALLOWED_CODE = 'MODEL_NOT_ALLOWED';\n\ninterface ModelNotAllowedErrorLike extends Error {\n code: typeof MODEL_NOT_ALLOWED_CODE;\n allowed?: unknown;\n attempted?: unknown;\n offendingLabel?: string;\n}\n\nfunction isModelNotAllowedError(error: unknown): error is ModelNotAllowedErrorLike {\n return error instanceof Error && (error as { code?: unknown }).code === MODEL_NOT_ALLOWED_CODE;\n}\n\nconst WORKFLOW_SCHEMA_VALIDATION_FAILED_CODE = 'WORKFLOW_SCHEMA_VALIDATION_FAILED';\n\nfunction isWorkflowSchemaValidationError(error: unknown): error is Error {\n return error instanceof Error && (error as { id?: unknown }).id === WORKFLOW_SCHEMA_VALIDATION_FAILED_CODE;\n}\n\nconst WORKFLOW_RESUME_ALREADY_CLAIMED_CODE = 'WORKFLOW_RESUME_ALREADY_CLAIMED';\n\nfunction isWorkflowResumeAlreadyClaimedError(error: unknown): error is Error {\n return error instanceof Error && (error as { id?: unknown }).id === WORKFLOW_RESUME_ALREADY_CLAIMED_CODE;\n}\n\n/**\n * Structural check for ZodError instances.\n *\n * Avoids `instanceof ZodError` because consumers can resolve `'zod'` to a\n * different package instance (e.g. `zod@^3`) than the one a server adapter is\n * bundled with (`zod@^4`). In that case `instanceof` is false and validation\n * errors fall through to a generic response that drops field-path information.\n *\n * See https://github.com/mastra-ai/mastra/issues/17167.\n */\nexport function isZodError(error: unknown): error is ZodError<any> {\n return (\n !!error &&\n typeof error === 'object' &&\n (error as { name?: unknown }).name === 'ZodError' &&\n Array.isArray((error as { issues?: unknown }).issues)\n );\n}\n\n/**\n * Formats a ZodError into a structured validation error response.\n * Returns an object with an error message and an array of field-specific issues.\n */\nexport function formatZodError(\n error: ZodErrorLike,\n context: string,\n): { error: string; issues: Array<{ field: string; message: string }> } {\n const issues = error.issues.map(e => ({\n field: e.path.length > 0 ? e.path.map(p => String(p)).join('.') : 'root',\n message: e.message,\n }));\n\n return {\n error: `Invalid ${context}`,\n issues,\n };\n}\n\n// Helper to handle errors consistently\nexport function handleError(error: unknown, defaultMessage: string): never {\n if (isModelNotAllowedError(error)) {\n const body = {\n error: {\n code: error.code,\n message: error.message,\n allowed: error.allowed,\n attempted: error.attempted,\n offendingLabel: error.offendingLabel,\n },\n };\n const res = new Response(JSON.stringify(body), {\n status: 422,\n headers: { 'content-type': 'application/json' },\n });\n throw new HTTPException(422, {\n res,\n message: error.message,\n cause: error,\n });\n }\n\n // A losing concurrent resume is a conflict on run state, not a malformed request, so it maps\n // to 409 and clients can distinguish it from a 400/500 and re-read the run.\n if (isWorkflowResumeAlreadyClaimedError(error)) {\n throw new HTTPException(409, {\n message: error.message,\n stack: error.stack,\n cause: error,\n });\n }\n\n if (isWorkflowSchemaValidationError(error)) {\n throw new HTTPException(400, {\n message: error.message,\n stack: error.stack,\n cause: error,\n });\n }\n\n const apiError = error as ApiError;\n\n const apiErrorStatus = apiError.status || apiError.details?.status || 500;\n\n throw new HTTPException(apiErrorStatus as StatusCode, {\n message: apiError.message || defaultMessage,\n stack: apiError.stack,\n cause: apiError.cause,\n });\n}\n"],"mappings":";;;;;;;;;;;;;;AA2BA,MAAM,yBAAyB;AAS/B,SAAS,uBAAuB,OAAmD;CACjF,OAAO,iBAAiB,SAAU,MAA6B,SAAS;AAC1E;AAEA,MAAM,yCAAyC;AAE/C,SAAS,gCAAgC,OAAgC;CACvE,OAAO,iBAAiB,SAAU,MAA2B,OAAO;AACtE;AAEA,MAAM,uCAAuC;AAE7C,SAAS,oCAAoC,OAAgC;CAC3E,OAAO,iBAAiB,SAAU,MAA2B,OAAO;AACtE;;;;;;;;;;;AAYA,SAAgB,WAAW,OAAwC;CACjE,OACE,CAAC,CAAC,SACF,OAAO,UAAU,YAChB,MAA6B,SAAS,cACvC,MAAM,QAAS,MAA+B,MAAM;AAExD;;;;;AAMA,SAAgB,eACd,OACA,SACsE;CACtE,MAAM,SAAS,MAAM,OAAO,KAAI,OAAM;EACpC,OAAO,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,KAAI,MAAK,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI;EAClE,SAAS,EAAE;CACb,EAAE;CAEF,OAAO;EACL,OAAO,WAAW;EAClB;CACF;AACF;AAGA,SAAgB,YAAY,OAAgB,gBAA+B;CACzE,IAAI,uBAAuB,KAAK,GAAG;EACjC,MAAM,OAAO,EACX,OAAO;GACL,MAAM,MAAM;GACZ,SAAS,MAAM;GACf,SAAS,MAAM;GACf,WAAW,MAAM;GACjB,gBAAgB,MAAM;EACxB,EACF;EAKA,MAAM,IAAIA,uBAAAA,cAAc,KAAK;GAC3B,KAAA,IALc,SAAS,KAAK,UAAU,IAAI,GAAG;IAC7C,QAAQ;IACR,SAAS,EAAE,gBAAgB,mBAAmB;GAChD,CAEI;GACF,SAAS,MAAM;GACf,OAAO;EACT,CAAC;CACH;CAIA,IAAI,oCAAoC,KAAK,GAC3C,MAAM,IAAIA,uBAAAA,cAAc,KAAK;EAC3B,SAAS,MAAM;EACf,OAAO,MAAM;EACb,OAAO;CACT,CAAC;CAGH,IAAI,gCAAgC,KAAK,GACvC,MAAM,IAAIA,uBAAAA,cAAc,KAAK;EAC3B,SAAS,MAAM;EACf,OAAO,MAAM;EACb,OAAO;CACT,CAAC;CAGH,MAAM,WAAW;CAIjB,MAAM,IAAIA,uBAAAA,cAFa,SAAS,UAAU,SAAS,SAAS,UAAU,KAEhB;EACpD,SAAS,SAAS,WAAW;EAC7B,OAAO,SAAS;EAChB,OAAO,SAAS;CAClB,CAAC;AACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/error.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAMpC;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,KAAK,CAAC;QACZ,IAAI,EAAE,WAAW,EAAE,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;CACJ;AA+BD;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAAC,GAAG,CAAC,CAOjE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,MAAM,GACd;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAUtE;AAGD,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,GAAG,KAAK,CAuCzE"}
1
+ {"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../../src/server/handlers/error.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAMpC;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,KAAK,CAAC;QACZ,IAAI,EAAE,WAAW,EAAE,CAAC;QACpB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC,CAAC;CACJ;AAqCD;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,QAAQ,CAAC,GAAG,CAAC,CAOjE;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,YAAY,EACnB,OAAO,EAAE,MAAM,GACd;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAUtE;AAGD,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,GAAG,KAAK,CAiDzE"}
@@ -18,6 +18,10 @@ const WORKFLOW_SCHEMA_VALIDATION_FAILED_CODE = "WORKFLOW_SCHEMA_VALIDATION_FAILE
18
18
  function isWorkflowSchemaValidationError(error) {
19
19
  return error instanceof Error && error.id === WORKFLOW_SCHEMA_VALIDATION_FAILED_CODE;
20
20
  }
21
+ const WORKFLOW_RESUME_ALREADY_CLAIMED_CODE = "WORKFLOW_RESUME_ALREADY_CLAIMED";
22
+ function isWorkflowResumeAlreadyClaimedError(error) {
23
+ return error instanceof Error && error.id === WORKFLOW_RESUME_ALREADY_CLAIMED_CODE;
24
+ }
21
25
  /**
22
26
  * Structural check for ZodError instances.
23
27
  *
@@ -63,6 +67,11 @@ function handleError(error, defaultMessage) {
63
67
  cause: error
64
68
  });
65
69
  }
70
+ if (isWorkflowResumeAlreadyClaimedError(error)) throw new HTTPException(409, {
71
+ message: error.message,
72
+ stack: error.stack,
73
+ cause: error
74
+ });
66
75
  if (isWorkflowSchemaValidationError(error)) throw new HTTPException(400, {
67
76
  message: error.message,
68
77
  stack: error.stack,
@@ -1 +1 @@
1
- {"version":3,"file":"error.js","names":[],"sources":["../../../src/server/handlers/error.ts"],"sourcesContent":["import type { ZodError } from 'zod';\n\nimport { HTTPException } from '../http-exception';\nimport type { StatusCode } from '../http-exception';\nimport type { ApiError } from '../types';\n\n/**\n * Duck-typed interface for ZodError-like objects.\n * Note: Zod v4 uses PropertyKey[] (string | number | symbol) for path.\n */\nexport interface ZodErrorLike {\n issues: Array<{\n path: PropertyKey[];\n message: string;\n }>;\n}\n\n/**\n * Recognition for `ModelNotAllowedError` from `@mastra/core/agent-builder/ee`.\n *\n * Inlined as a duck check rather than imported so that `handleError` (wired\n * into every route) does not force a load-time dependency on the\n * `@mastra/core/agent-builder/ee` subpath. That subpath only ships in\n * `@mastra/core >= 1.34.0`; deploys whose bundled `@mastra/server` resolves\n * against an older core would otherwise crash at startup with\n * `ERR_MODULE_NOT_FOUND` on `@mastra/core/dist/agent-builder/ee/index.js`.\n */\nconst MODEL_NOT_ALLOWED_CODE = 'MODEL_NOT_ALLOWED';\n\ninterface ModelNotAllowedErrorLike extends Error {\n code: typeof MODEL_NOT_ALLOWED_CODE;\n allowed?: unknown;\n attempted?: unknown;\n offendingLabel?: string;\n}\n\nfunction isModelNotAllowedError(error: unknown): error is ModelNotAllowedErrorLike {\n return error instanceof Error && (error as { code?: unknown }).code === MODEL_NOT_ALLOWED_CODE;\n}\n\nconst WORKFLOW_SCHEMA_VALIDATION_FAILED_CODE = 'WORKFLOW_SCHEMA_VALIDATION_FAILED';\n\nfunction isWorkflowSchemaValidationError(error: unknown): error is Error {\n return error instanceof Error && (error as { id?: unknown }).id === WORKFLOW_SCHEMA_VALIDATION_FAILED_CODE;\n}\n\n/**\n * Structural check for ZodError instances.\n *\n * Avoids `instanceof ZodError` because consumers can resolve `'zod'` to a\n * different package instance (e.g. `zod@^3`) than the one a server adapter is\n * bundled with (`zod@^4`). In that case `instanceof` is false and validation\n * errors fall through to a generic response that drops field-path information.\n *\n * See https://github.com/mastra-ai/mastra/issues/17167.\n */\nexport function isZodError(error: unknown): error is ZodError<any> {\n return (\n !!error &&\n typeof error === 'object' &&\n (error as { name?: unknown }).name === 'ZodError' &&\n Array.isArray((error as { issues?: unknown }).issues)\n );\n}\n\n/**\n * Formats a ZodError into a structured validation error response.\n * Returns an object with an error message and an array of field-specific issues.\n */\nexport function formatZodError(\n error: ZodErrorLike,\n context: string,\n): { error: string; issues: Array<{ field: string; message: string }> } {\n const issues = error.issues.map(e => ({\n field: e.path.length > 0 ? e.path.map(p => String(p)).join('.') : 'root',\n message: e.message,\n }));\n\n return {\n error: `Invalid ${context}`,\n issues,\n };\n}\n\n// Helper to handle errors consistently\nexport function handleError(error: unknown, defaultMessage: string): never {\n if (isModelNotAllowedError(error)) {\n const body = {\n error: {\n code: error.code,\n message: error.message,\n allowed: error.allowed,\n attempted: error.attempted,\n offendingLabel: error.offendingLabel,\n },\n };\n const res = new Response(JSON.stringify(body), {\n status: 422,\n headers: { 'content-type': 'application/json' },\n });\n throw new HTTPException(422, {\n res,\n message: error.message,\n cause: error,\n });\n }\n\n if (isWorkflowSchemaValidationError(error)) {\n throw new HTTPException(400, {\n message: error.message,\n stack: error.stack,\n cause: error,\n });\n }\n\n const apiError = error as ApiError;\n\n const apiErrorStatus = apiError.status || apiError.details?.status || 500;\n\n throw new HTTPException(apiErrorStatus as StatusCode, {\n message: apiError.message || defaultMessage,\n stack: apiError.stack,\n cause: apiError.cause,\n });\n}\n"],"mappings":";;;;;;;;;;;;AA2BA,MAAM,yBAAyB;AAS/B,SAAS,uBAAuB,OAAmD;CACjF,OAAO,iBAAiB,SAAU,MAA6B,SAAS;AAC1E;AAEA,MAAM,yCAAyC;AAE/C,SAAS,gCAAgC,OAAgC;CACvE,OAAO,iBAAiB,SAAU,MAA2B,OAAO;AACtE;;;;;;;;;;;AAYA,SAAgB,WAAW,OAAwC;CACjE,OACE,CAAC,CAAC,SACF,OAAO,UAAU,YAChB,MAA6B,SAAS,cACvC,MAAM,QAAS,MAA+B,MAAM;AAExD;;;;;AAMA,SAAgB,eACd,OACA,SACsE;CACtE,MAAM,SAAS,MAAM,OAAO,KAAI,OAAM;EACpC,OAAO,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,KAAI,MAAK,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI;EAClE,SAAS,EAAE;CACb,EAAE;CAEF,OAAO;EACL,OAAO,WAAW;EAClB;CACF;AACF;AAGA,SAAgB,YAAY,OAAgB,gBAA+B;CACzE,IAAI,uBAAuB,KAAK,GAAG;EACjC,MAAM,OAAO,EACX,OAAO;GACL,MAAM,MAAM;GACZ,SAAS,MAAM;GACf,SAAS,MAAM;GACf,WAAW,MAAM;GACjB,gBAAgB,MAAM;EACxB,EACF;EAKA,MAAM,IAAI,cAAc,KAAK;GAC3B,KAAA,IALc,SAAS,KAAK,UAAU,IAAI,GAAG;IAC7C,QAAQ;IACR,SAAS,EAAE,gBAAgB,mBAAmB;GAChD,CAEI;GACF,SAAS,MAAM;GACf,OAAO;EACT,CAAC;CACH;CAEA,IAAI,gCAAgC,KAAK,GACvC,MAAM,IAAI,cAAc,KAAK;EAC3B,SAAS,MAAM;EACf,OAAO,MAAM;EACb,OAAO;CACT,CAAC;CAGH,MAAM,WAAW;CAIjB,MAAM,IAAI,cAFa,SAAS,UAAU,SAAS,SAAS,UAAU,KAEhB;EACpD,SAAS,SAAS,WAAW;EAC7B,OAAO,SAAS;EAChB,OAAO,SAAS;CAClB,CAAC;AACH"}
1
+ {"version":3,"file":"error.js","names":[],"sources":["../../../src/server/handlers/error.ts"],"sourcesContent":["import type { ZodError } from 'zod';\n\nimport { HTTPException } from '../http-exception';\nimport type { StatusCode } from '../http-exception';\nimport type { ApiError } from '../types';\n\n/**\n * Duck-typed interface for ZodError-like objects.\n * Note: Zod v4 uses PropertyKey[] (string | number | symbol) for path.\n */\nexport interface ZodErrorLike {\n issues: Array<{\n path: PropertyKey[];\n message: string;\n }>;\n}\n\n/**\n * Recognition for `ModelNotAllowedError` from `@mastra/core/agent-builder/ee`.\n *\n * Inlined as a duck check rather than imported so that `handleError` (wired\n * into every route) does not force a load-time dependency on the\n * `@mastra/core/agent-builder/ee` subpath. That subpath only ships in\n * `@mastra/core >= 1.34.0`; deploys whose bundled `@mastra/server` resolves\n * against an older core would otherwise crash at startup with\n * `ERR_MODULE_NOT_FOUND` on `@mastra/core/dist/agent-builder/ee/index.js`.\n */\nconst MODEL_NOT_ALLOWED_CODE = 'MODEL_NOT_ALLOWED';\n\ninterface ModelNotAllowedErrorLike extends Error {\n code: typeof MODEL_NOT_ALLOWED_CODE;\n allowed?: unknown;\n attempted?: unknown;\n offendingLabel?: string;\n}\n\nfunction isModelNotAllowedError(error: unknown): error is ModelNotAllowedErrorLike {\n return error instanceof Error && (error as { code?: unknown }).code === MODEL_NOT_ALLOWED_CODE;\n}\n\nconst WORKFLOW_SCHEMA_VALIDATION_FAILED_CODE = 'WORKFLOW_SCHEMA_VALIDATION_FAILED';\n\nfunction isWorkflowSchemaValidationError(error: unknown): error is Error {\n return error instanceof Error && (error as { id?: unknown }).id === WORKFLOW_SCHEMA_VALIDATION_FAILED_CODE;\n}\n\nconst WORKFLOW_RESUME_ALREADY_CLAIMED_CODE = 'WORKFLOW_RESUME_ALREADY_CLAIMED';\n\nfunction isWorkflowResumeAlreadyClaimedError(error: unknown): error is Error {\n return error instanceof Error && (error as { id?: unknown }).id === WORKFLOW_RESUME_ALREADY_CLAIMED_CODE;\n}\n\n/**\n * Structural check for ZodError instances.\n *\n * Avoids `instanceof ZodError` because consumers can resolve `'zod'` to a\n * different package instance (e.g. `zod@^3`) than the one a server adapter is\n * bundled with (`zod@^4`). In that case `instanceof` is false and validation\n * errors fall through to a generic response that drops field-path information.\n *\n * See https://github.com/mastra-ai/mastra/issues/17167.\n */\nexport function isZodError(error: unknown): error is ZodError<any> {\n return (\n !!error &&\n typeof error === 'object' &&\n (error as { name?: unknown }).name === 'ZodError' &&\n Array.isArray((error as { issues?: unknown }).issues)\n );\n}\n\n/**\n * Formats a ZodError into a structured validation error response.\n * Returns an object with an error message and an array of field-specific issues.\n */\nexport function formatZodError(\n error: ZodErrorLike,\n context: string,\n): { error: string; issues: Array<{ field: string; message: string }> } {\n const issues = error.issues.map(e => ({\n field: e.path.length > 0 ? e.path.map(p => String(p)).join('.') : 'root',\n message: e.message,\n }));\n\n return {\n error: `Invalid ${context}`,\n issues,\n };\n}\n\n// Helper to handle errors consistently\nexport function handleError(error: unknown, defaultMessage: string): never {\n if (isModelNotAllowedError(error)) {\n const body = {\n error: {\n code: error.code,\n message: error.message,\n allowed: error.allowed,\n attempted: error.attempted,\n offendingLabel: error.offendingLabel,\n },\n };\n const res = new Response(JSON.stringify(body), {\n status: 422,\n headers: { 'content-type': 'application/json' },\n });\n throw new HTTPException(422, {\n res,\n message: error.message,\n cause: error,\n });\n }\n\n // A losing concurrent resume is a conflict on run state, not a malformed request, so it maps\n // to 409 and clients can distinguish it from a 400/500 and re-read the run.\n if (isWorkflowResumeAlreadyClaimedError(error)) {\n throw new HTTPException(409, {\n message: error.message,\n stack: error.stack,\n cause: error,\n });\n }\n\n if (isWorkflowSchemaValidationError(error)) {\n throw new HTTPException(400, {\n message: error.message,\n stack: error.stack,\n cause: error,\n });\n }\n\n const apiError = error as ApiError;\n\n const apiErrorStatus = apiError.status || apiError.details?.status || 500;\n\n throw new HTTPException(apiErrorStatus as StatusCode, {\n message: apiError.message || defaultMessage,\n stack: apiError.stack,\n cause: apiError.cause,\n });\n}\n"],"mappings":";;;;;;;;;;;;AA2BA,MAAM,yBAAyB;AAS/B,SAAS,uBAAuB,OAAmD;CACjF,OAAO,iBAAiB,SAAU,MAA6B,SAAS;AAC1E;AAEA,MAAM,yCAAyC;AAE/C,SAAS,gCAAgC,OAAgC;CACvE,OAAO,iBAAiB,SAAU,MAA2B,OAAO;AACtE;AAEA,MAAM,uCAAuC;AAE7C,SAAS,oCAAoC,OAAgC;CAC3E,OAAO,iBAAiB,SAAU,MAA2B,OAAO;AACtE;;;;;;;;;;;AAYA,SAAgB,WAAW,OAAwC;CACjE,OACE,CAAC,CAAC,SACF,OAAO,UAAU,YAChB,MAA6B,SAAS,cACvC,MAAM,QAAS,MAA+B,MAAM;AAExD;;;;;AAMA,SAAgB,eACd,OACA,SACsE;CACtE,MAAM,SAAS,MAAM,OAAO,KAAI,OAAM;EACpC,OAAO,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,KAAI,MAAK,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI;EAClE,SAAS,EAAE;CACb,EAAE;CAEF,OAAO;EACL,OAAO,WAAW;EAClB;CACF;AACF;AAGA,SAAgB,YAAY,OAAgB,gBAA+B;CACzE,IAAI,uBAAuB,KAAK,GAAG;EACjC,MAAM,OAAO,EACX,OAAO;GACL,MAAM,MAAM;GACZ,SAAS,MAAM;GACf,SAAS,MAAM;GACf,WAAW,MAAM;GACjB,gBAAgB,MAAM;EACxB,EACF;EAKA,MAAM,IAAI,cAAc,KAAK;GAC3B,KAAA,IALc,SAAS,KAAK,UAAU,IAAI,GAAG;IAC7C,QAAQ;IACR,SAAS,EAAE,gBAAgB,mBAAmB;GAChD,CAEI;GACF,SAAS,MAAM;GACf,OAAO;EACT,CAAC;CACH;CAIA,IAAI,oCAAoC,KAAK,GAC3C,MAAM,IAAI,cAAc,KAAK;EAC3B,SAAS,MAAM;EACf,OAAO,MAAM;EACb,OAAO;CACT,CAAC;CAGH,IAAI,gCAAgC,KAAK,GACvC,MAAM,IAAI,cAAc,KAAK;EAC3B,SAAS,MAAM;EACf,OAAO,MAAM;EACb,OAAO;CACT,CAAC;CAGH,MAAM,WAAW;CAIjB,MAAM,IAAI,cAFa,SAAS,UAAU,SAAS,SAAS,UAAU,KAEhB;EACpD,SAAS,SAAS,WAAW;EAC7B,OAAO,SAAS;EAChB,OAAO,SAAS;CAClB,CAAC;AACH"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/server",
3
- "version": "1.60.0",
3
+ "version": "1.60.1-alpha.0",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "files": [
@@ -117,14 +117,14 @@
117
117
  "zod": "^4.4.3",
118
118
  "zod-to-ts": "^2.1.0",
119
119
  "@internal/core": "0.1.2",
120
- "@internal/types-builder": "0.0.99",
121
- "@internal/test-utils": "0.0.60",
122
120
  "@internal/lint": "0.0.124",
123
- "@internal/voice": "0.0.22",
124
121
  "@internal/storage-test-utils": "0.0.120",
122
+ "@internal/voice": "0.0.22",
123
+ "@internal/types-builder": "0.0.99",
124
+ "@internal/test-utils": "0.0.60",
125
125
  "@mastra/agent-builder": "1.1.13",
126
- "@mastra/core": "1.60.0",
127
- "@mastra/schema-compat": "1.3.7"
126
+ "@mastra/schema-compat": "1.3.7",
127
+ "@mastra/core": "1.60.1-alpha.0"
128
128
  },
129
129
  "homepage": "https://mastra.ai",
130
130
  "repository": {