Error Handling
Throw each SDK error class to inspect status, code, context, and diagnostic. The same shape arrives in your real catch blocks.
Click any error class above to throw it and inspect the captured fields.
error-classes.ts
import {
BadRequestError, // 400
AuthError, // 401
ForbiddenError, // 403
NotFoundError, // 404
ConflictError, // 409
ValidationError, // 422
RateLimitError, // 429
ServerError, // 500
// AI-specific subclasses (all extend ReoptSDKError)
CreditLimitError, // 402 — AI credit balance exhausted
ModelAccessError, // 403 — model not allowed for this plan tier
ModelNotFoundError, // 404 — unknown model id
ContentFilterError, // 422 — blocked by moderation policy
} from "@reopt-ai/brandapp-sdk";
try {
await sdk.eav.records.get("ent_123", "rec_missing");
} catch (error) {
// Use `instanceof` to branch on specific HTTP semantics
if (error instanceof NotFoundError) {
return null; // soft-fail
}
if (error instanceof ConflictError) {
// Refetch and retry
}
if (error instanceof RateLimitError) {
// Back off; `error.diagnostic.fix` includes a retry-after hint
}
if (error instanceof ValidationError) {
return error.toFieldMap();
}
if (error instanceof CreditLimitError) {
// 402 — prompt the user to top up AI credits
}
if (error instanceof ModelAccessError) {
// 403 — fall back to an allowed model or prompt a plan upgrade
}
throw error;
}is-reopt-sdk-error.ts
import { isReoptSDKError } from "@reopt-ai/brandapp-sdk";
try {
await sdk.eav.records.create(entityId, { values: {} });
} catch (error) {
if (isReoptSDKError(error)) {
console.log(error.message); // Human-readable message (with [METHOD URL] prefix)
console.log(error.code); // Error code (e.g. "VALIDATION_ERROR", "NOT_FOUND")
console.log(error.status); // HTTP status code (400, 403, 404, ...)
console.log(error.context); // { method, url, attempt? } — request context
console.log(error.diagnostic); // { cause, fix, envVar?, doc? } — agent-readable hints
}
}is-validation-error.ts
import { isValidationError } from "@reopt-ai/brandapp-sdk";
try {
await sdk.eav.records.create(entityId, { values: {} });
} catch (error) {
if (isValidationError(error)) {
// fieldErrors is an array of { field, message, code? }
error.fieldErrors.forEach((fe) => {
console.log(`${fe.field}: ${fe.message}`);
});
// "name: 필수 필드입니다"
// "email: 올바른 이메일 형식이 아닙니다"
// Get a single field's message
const emailError = error.getFieldError("email");
// Or convert to a flat record for form libraries
const fieldMap = error.toFieldMap();
// { name: "필수 필드입니다", email: "올바른 이메일 형식이 아닙니다" }
}
}diagnostic.ts
import { isCreditLimitError } from "@reopt-ai/brandapp-sdk";
// SDK errors carry agent-readable diagnostics under `error.diagnostic`.
// Every built-in error class populates this automatically.
type ErrorDiagnostic = {
cause: string; // Human-readable cause
fix: string; // Step the developer (or AI agent) should take
envVar?: string; // Related env var (when applicable)
doc?: string; // Path inside @reopt-ai/brandapp-sdk/docs/
};
// Example: AI credits exhausted (CreditLimitError, HTTP 402)
if (isCreditLimitError(error)) {
console.log(error.diagnostic?.cause); // "BrandApp AI 크레딧 잔액 부족"
console.log(error.diagnostic?.fix); // "Studio → BrandApp → AI 크레딧 페이지에서 충전"
console.log(error.diagnostic?.doc); // "docs/errors.md#credit_limit"
}lib/api-error.ts (enhanced)
import { NextResponse } from "next/server";
import {
isReoptSDKError,
isValidationError,
} from "@reopt-ai/brandapp-sdk";
// Centralized API error handler — maps SDK errors to HTTP responses.
export function handleApiError(error: unknown): NextResponse {
if (isValidationError(error)) {
return NextResponse.json(
{
error: error.message,
code: error.code,
fieldErrors: error.toFieldMap(),
diagnostic: error.diagnostic,
},
{ status: error.status },
);
}
if (isReoptSDKError(error)) {
return NextResponse.json(
{
error: error.message,
code: error.code,
diagnostic: error.diagnostic,
},
{ status: error.status },
);
}
const message =
error instanceof Error ? error.message : "Internal Server Error";
return NextResponse.json({ error: message }, { status: 500 });
}