eyaltoledano/claude-task-master · error

API_ERROR

API_ERROR

Error message

API returned non-JSON response (${response.status}): ${text.substring(0, 100)}...

What it means

callGenerateBriefEndpoint checks the Content-Type header of the brief-generation HTTP response; if it is not application/json the library reads the body text and returns an API_ERROR result embedding the HTTP status and the first 100 characters. This typically means the request hit an HTML error page, a proxy login page, or a non-JSON gateway response instead of the Hamster API.

Source

Thrown at packages/tm-core/src/modules/integration/services/export.service.ts:1108

		try {
			const response = await fetch(apiUrl, {
				method: 'POST',
				headers: {
					'Content-Type': 'application/json',
					Authorization: `Bearer ${accessToken}`,
					'x-account-id': accountId // Also send as header for redundancy
				},
				body: JSON.stringify(requestBody)
			});

			// Check content type to avoid JSON parse errors on HTML responses (e.g., 404 pages)
			const contentType = response.headers.get('content-type') || '';
			if (!contentType.includes('application/json')) {
				const text = await response.text();
				return {
					success: false,
					error: {
						code: 'API_ERROR',
						message: `API returned non-JSON response (${response.status}): ${text.substring(0, 100)}...`
					}
				};
			}

			const jsonData = await response.json();
			const result = jsonData as GenerateBriefResponse;

			if (!response.ok || !result.success) {
				// Try to extract error from various possible response formats
				const errorMessage =
					result.error?.message ||
					(jsonData as any)?.message ||
					(jsonData as any)?.error ||
					`API request failed: ${response.status} - ${response.statusText}`;

				const errorCode =
					result.error?.code ||

View on GitHub (pinned to c0c98d367c)

Solutions

  1. Inspect the embedded body snippet and HTTP status in the message to identify who returned the non-JSON response.
  2. Verify the API base URL / environment configuration points at the Hamster API, not a website.
  3. Check proxy/VPN settings; try from a network without an intercepting proxy.
  4. Retry later if the status is 5xx (server-side outage); check Hamster status page.
  5. If a WAF/rate limiter blocks you, reduce request frequency or contact support.

Example fix

// before (behind intercepting proxy)
const res = await fetch('https://wrong-host/briefs/generate', ...);
// after
const res = await fetch('https://api.hamster.example/.../generate', { headers: { Authorization: `Bearer ${token}` } });
Defensive patterns

Strategy: try-catch

Validate before calling

const probe = await fetch(apiBase, { headers: { Accept: 'application/json' } });
const ct = probe.headers.get('content-type') || '';
if (!ct.includes('application/json')) throw new Error('Endpoint is not returning JSON - check base URL/proxy');

Type guard

function isApiError(r: GenerateBriefResult): r is GenerateBriefResult & { success: false; error: { code: 'API_ERROR' } } {
  return !r.success && r.error?.code === 'API_ERROR';
}

Try / catch

const result = await exportService.generateBriefFromTasks(opts);
if (!result.success && result.error?.code === 'API_ERROR') {
  // message contains status + body snippet; log it and retry with backoff or alert
  logger.error('non-JSON API response', { detail: result.error.message });
}

Prevention

When it happens

Trigger: The generate-brief endpoint (or an intermediary) responds with text/html or text/plain - e.g. a 502/504 gateway HTML page, an auth-redirect HTML page, a captive portal, or a proxy error page.

Common situations: Corporate proxies/VPNs intercepting requests, wrong base URL pointing at a website instead of the API, server outages returning HTML error pages, or rate-limit/WAF pages (Cloudflare) blocking the request.

Related errors


AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29). Data as JSON: /api/errors/385eb72c06f56212. Report an issue: GitHub.