Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/twelve-horses-mix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@clerk/shared": patch
---

Rename static properties from 'name' to 'kind' in ClerkError class
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Clarify scope of the change.

The rename applies to multiple error classes/utilities, not just ClerkError. Please update the note so downstream readers understand the broader impact.

🧰 Tools
🪛 LanguageTool

[grammar] ~5-~5: There might be a mistake here.
Context: ...static properties from 'name' to 'kind' in ClerkError class

(QB_NEW_EN)

🤖 Prompt for AI Agents
In .changeset/twelve-horses-mix.md around line 5, the note incorrectly limits
the rename to only the ClerkError class; update the changelog entry to state
that static property 'name' has been renamed to 'kind' across multiple error
classes and related utilities (e.g., ClerkError and other error
subclasses/utilities) so downstream consumers understand the broader,
codebase-wide impact; make the wording explicit and include a brief list or
phrase such as "applies to ClerkError and other error classes/utilities" and
mention any public APIs affected.

2 changes: 1 addition & 1 deletion packages/shared/src/errors/clerkApiError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export type ClerkApiErrorMeta = Record<string, unknown>;
* This error contains the specific error message, code, and any additional metadata that was returned by the Clerk API.
*/
export class ClerkAPIError<Meta extends ClerkApiErrorMeta = any> implements ClerkAPIErrorInterface {
readonly name = 'ClerkApiError';
static kind = 'ClerkApiError';
readonly code: string;
readonly message: string;
readonly longMessage: string | undefined;
Expand Down
2 changes: 1 addition & 1 deletion packages/shared/src/errors/clerkApiResponseError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ interface ClerkAPIResponseOptions extends Omit<ClerkErrorParams, 'message' | 'co
}

export class ClerkAPIResponseError extends ClerkError implements ClerkAPIResponseErrorInterface {
static name = 'ClerkAPIResponseError';
static kind = 'ClerkAPIResponseError';
status: number;
clerkTraceId?: string;
retryAfter?: number;
Expand Down
4 changes: 2 additions & 2 deletions packages/shared/src/errors/clerkError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export interface ClerkErrorParams {
const __DEV__ = true;

export class ClerkError extends Error {
static name = 'ClerkError';
static kind = 'ClerkError';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Add TypeScript constraint for subclass static kind property.

While the static kind property works for this base class, there's no type-level constraint ensuring that subclasses define their own static kind. This is critical because line 49 uses new.target.kind, which will be undefined if a subclass omits this property, potentially causing runtime errors in formatMessage.

Consider adding an abstract static accessor or documenting the requirement:

 export class ClerkError extends Error {
   static kind = 'ClerkError';
+  // Subclasses must define their own static kind property
   readonly clerkError = true as const;

Alternatively, provide a runtime check in the constructor:

constructor(opts: ClerkErrorParams) {
  const kind = (this.constructor as typeof ClerkError).kind;
  if (!kind) {
    throw new Error(`${this.constructor.name} must define a static 'kind' property`);
  }
  super(new.target.formatMessage(kind, opts.message, opts.code, opts.docsUrl), { cause: opts.cause });
  // ...
}
🤖 Prompt for AI Agents
In packages/shared/src/errors/clerkError.ts around line 37, enforce that
subclasses provide a static kind to avoid new.target.kind being undefined: add
an abstract static getter (e.g. abstract static get kind(): string) to the
ClerkError class signature so TypeScript forces subclasses to declare it, and
update the constructor to reference new.target.kind as before; additionally
(optional) add a small runtime guard in the constructor that throws a clear
Error if the resolved kind is falsy to catch any JS consumers.

readonly clerkError = true as const;
readonly code: string;
readonly longMessage: string | undefined;
Expand All @@ -46,7 +46,7 @@ export class ClerkError extends Error {
}

constructor(opts: ClerkErrorParams) {
super(new.target.formatMessage(new.target.name, opts.message, opts.code, opts.docsUrl), { cause: opts.cause });
super(new.target.formatMessage(new.target.kind, opts.message, opts.code, opts.docsUrl), { cause: opts.cause });
Object.setPrototypeOf(this, ClerkError.prototype);
this.code = opts.code;
this.docsUrl = opts.docsUrl;
Expand Down
2 changes: 1 addition & 1 deletion packages/shared/src/errors/clerkRuntimeError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type ClerkRuntimeErrorOptions = Omit<ClerkErrorParams, 'message'>;
* throw new ClerkRuntimeError('An error occurred', { code: 'password_invalid' });
*/
export class ClerkRuntimeError extends ClerkError {
static name = 'ClerkRuntimeError';
static kind = 'ClerkRuntimeError';
/**
* @deprecated Use `clerkError` property instead. This property is maintained for backward compatibility.
*/
Expand Down
4 changes: 2 additions & 2 deletions packages/shared/src/errors/createErrorTypeGuard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ type Value = unknown;
* ```
*/
export function createErrorTypeGuard<T extends new (...args: any[]) => Value>(
ErrorClass: T,
ErrorClass: T & { kind?: string },
): {
(error: Value): error is InstanceType<T>;
(this: Value): this is InstanceType<T>;
} {
function typeGuard(this: Value, error?: Value): error is InstanceType<T> {
const target = error ?? this;
if (!target) {
throw new TypeError(`${ErrorClass.name} type guard requires an error object`);
throw new TypeError(`${ErrorClass.kind || ErrorClass.name} type guard requires an error object`);
}
return target instanceof ErrorClass;
}
Expand Down
Loading