에러 처리
모든 SDK 에러는 OpenEchoError를 상속하고 code·httpStatus·message를 보존합니다. 이 가이드는 실무 처리 패턴을 다룹니다 — 전체 에러 클래스 표는 에러 레퍼런스를 참조하세요.
instanceof 분기
구체 클래스로 먼저 분기하고, 마지막에 OpenEchoError로 공통 처리합니다.
ts
try {
await oe.broadcast.tts.send({ /* ... */ });
} catch (err) {
if (err instanceof CapabilityDenied) {
// TTS 권한 없음
} else if (err instanceof UsageCapExceeded) {
showMessage("일일 방송 한도를 초과했습니다.");
} else if (err instanceof OpenEchoError) {
console.error(err.code, err.httpStatus, err.message);
}
}SSE(broadcast.subscribe) 에러는 throw되지 않고 onError 콜백으로 전달됩니다. try/catch가 아니라 콜백에서 처리하세요.
멱등성 재시도
네트워크 오류로 재시도할 때는 같은 idempotencyKey를 재사용해 중복 방송을 막습니다. 다른 페이로드에 같은 키를 쓰면 IdempotencyKeyReused(409)가 발생합니다.
ts
const key = crypto.randomUUID();
async function sendWithRetry(input) {
for (let attempt = 0; attempt < 3; attempt++) {
try {
return await oe.broadcast.tts.send({ ...input, idempotencyKey: key });
} catch (err) {
if (err instanceof RateLimited && attempt < 2) {
await sleep(2 ** attempt * 500); // 지수 백오프
continue;
}
throw err;
}
}
}게이트웨이 마스킹 부분 실패
dev 환경 CloudFront가 /api/* 4xx를 2xx+HTML로 치환하면 SDK는 GatewayMasked/InvalidApiResponse를 throw합니다. 여러 자원을 병렬 로드할 때 Promise.allSettled로 한 자원 실패가 전체를 무너뜨리지 않게 합니다.
ts
const [devRes, grpRes] = await Promise.allSettled([
oe.targets.list(),
oe.groups.list(),
]);
const devices = devRes.status === "fulfilled" ? devRes.value : [];
const groups = grpRes.status === "fulfilled" ? grpRes.value : [];
if (devRes.status === "rejected" || grpRes.status === "rejected") {
showPartialFailureNotice();
}도메인 잠금(OriginForbidden) 진단 절차는 에러 레퍼런스를 참조하세요.

