dubinc/dub · error
textData
Error message
textData
What it means
When the response content-type is not application/json, parseApiResponse reads the body as text and throws that raw text as the error message. This usually means the request hit something that did not return the Dub JSON API response — a proxy/CDN error page, HTML 502 page, or an outage.
Source
Thrown at packages/cli/src/utils/parser.ts:21
type AnyResponse = Response | NodeFetchResponse;
export async function parseApiResponse<T>(response: AnyResponse): Promise<T> {
const contentType = response.headers.get("content-type");
if (contentType?.includes("application/json")) {
const parsedData = await response.json();
if ("error" in parsedData) {
throw new Error((parsedData as APIError).error.message);
}
return parsedData as T;
}
const textData = await response.text();
throw new Error(textData);
}
View on GitHub (pinned to f216b94a24)
Solutions
- Inspect the thrown text — it contains the raw body (e.g. HTML) revealing the real intermediary error.
- Retry later or check Dub's status page if the text shows a gateway timeout/502/503.
- Verify the API base URL points to https://api.dub.co (or correct env) and not a web UI.
- Check proxy/firewall settings that may inject HTML error pages.
Example fix
// before baseUrl = 'https://dub.co'; // hits web app, returns HTML // after baseUrl = 'https://api.dub.co';
Defensive patterns
Strategy: fallback
Validate before calling
const base = process.env.DUB_API_BASE ?? "https://api.dub.co";
new URL(base); // fail fast on malformed base URL before any request
if (!base.startsWith("https://")) throw new Error("DUB_API_BASE must be an https API endpoint"); Type guard
function isJsonObject(text: string): boolean {
try { const v = JSON.parse(text); return typeof v === "object" && v !== null; } catch { return false; }
} Try / catch
try {
return await parseApiResponse(response);
} catch (e) {
const body = (e as Error).message;
if (/<html|502|503|gateway|cloudflare/i.test(body)) {
console.error("Dub API unreachable (non-JSON response). Retrying later.");
return fallbackValue; // or rethrow after retries
}
throw e;
} Prevention
- Point the client at the API host (api.dub.co), never the marketing site.
- Monitor Dub's status page and add outages to your runbook.
- Configure proxies to pass through API hosts without HTML interception.
- Distinguish infra failures from API errors by sniffing the thrown text for HTML.
When it happens
Trigger: Calls from `dub domains`/defaultDomains when the Dub API (or an intermediary) returns a non-JSON body: HTML error pages from proxies, plain-text 502/503 outage messages, or a wrong base URL hitting a non-API endpoint.
Common situations: Corporate proxy or Cloudflare returning an HTML block/timeout page; Dub API downtime; misconfigured DUB_API_BASE/localhost pointing at a UI server instead of the API.
Related errors
- (parsedData as APIError).error.message
- Failed to update workspace.
- Failed to fetch user info from Dub.
- Failed after ${maxRetries} retries. Last error: ${lastError.
AI-assisted analysis of dubinc/dub@f216b94a24 (2026-08-31).
Data as JSON: /api/errors/a6ba7c091b8db17f.
Report an issue: GitHub.