ruvnet/ruflo · warning · Error

Received empty response from ${url} but allowNull is not set

Error message

Received empty response from ${url} but allowNull is not set to true

What it means

Thrown by fetchJSON when the response was OK (2xx) but the body parsed to empty (no text or whitespace-only). Because the generic return type T is non-null, a null result is only allowed when the caller explicitly opts in via options.allowNull === true; otherwise the helper refuses to return null as T.

Source

Thrown at ruflo/src/ruvocal/src/lib/utils/fetchJSON.ts:19

export async function fetchJSON<T>(
	url: string,
	options?: {
		fetch?: typeof window.fetch;
		allowNull?: boolean;
	}
): Promise<T> {
	const response = await (options?.fetch ?? fetch)(url);
	if (!response.ok) {
		throw new Error(`Failed to fetch ${url}: ${response.status} ${response.statusText}`);
	}

	// Handle empty responses (which parse to null)
	const text = await response.text();
	if (!text || text.trim() === "") {
		if (options?.allowNull) {
			return null as T;
		}
		throw new Error(`Received empty response from ${url} but allowNull is not set to true`);
	}

	return JSON.parse(text);
}

View on GitHub (pinned to 6b01dc5a68)

Solutions

  1. If an empty/204 response is valid for this call, pass { allowNull: true } and handle T | null at the call site.
  2. If the endpoint should return JSON, fix the server to return a real body (or a proper 404).
  3. Check for an intercepting proxy (nginx try_files, a CDN) that is replacing the body with an empty page.
  4. Confirm Content-Type and that no middleware is converting 204 into 200-with-empty.

Example fix

// before
const data = await fetchJSON<MyType>(`${base}/api/thing/${id}`);
// after
const data = await fetchJSON<MyType | null>(`${base}/api/thing/${id}`, { allowNull: true });
if (data === null) return null;
Defensive patterns

Strategy: validation

Validate before calling

// decide based on the endpoint's contract before calling
const allowsEmpty = endpointReturnsEmptyOnSuccess(url);
const data = await fetchJSON<T | null>(url, { allowNull: allowsEmpty });
if (data === null && !allowsEmpty) throw new Error(`unexpected null from ${url}`);

Try / catch

try {
  return await fetchJSON<T>(url); // allowNull omitted intentionally
} catch (e) {
  if (String((e as Error)?.message ?? "").includes("allowNull is not set to true")) {
    return null as T; // empty body is valid for this caller
  }
  throw e;
}

Prevention

When it happens

Trigger: An endpoint returns 200 with an empty body (or 204 No Content with no body) — common for DELETE, ack-style POSTs, or a misconfigured proxy that strips the body. The caller did not pass allowNull: true.

Common situations: Calling a REST endpoint that legitimately returns 204; a backend that returns 200 + empty when a resource is not found instead of a real 404; switching fetchJSON to point at an endpoint whose contract is "empty on success".

Related errors


AI-assisted analysis of ruvnet/ruflo@6b01dc5a68 (2026-08-12). Data as JSON: /api/errors/56bfd604b6c1ca23. Report an issue: GitHub.