jackwener/OpenCLI · error · CommandExecutionError
${label} returned a non-JSON response
Error message
${label} returned a non-JSON response What it means
atlassianRequest throws this when the HTTP response was OK (2xx) but the body could not be parsed as JSON — the parsed result is a string. The Atlassian REST API is expected to return JSON, so a string body almost always means something other than the API answered (HTML login/SSO page, proxy intercept, or a wrong URL that serves HTML with 200).
Source
Thrown at clis/_atlassian/shared.js:218
);
}
if (resp.status === 404) {
throw new EmptyResultError(label, `Atlassian returned 404 for ${url}.`);
}
if (resp.status === 409) {
throw new CommandExecutionError(
`${label} returned HTTP 409: ${summarizeApiError(parsed, 'version conflict')}`,
'Reload the current Confluence page version and retry the update.',
);
}
if (resp.status === 429) {
throw new CommandExecutionError(`${label} returned HTTP 429 (rate limited)`, 'Wait and retry with a smaller limit.');
}
if (!resp.ok) {
throw new CommandExecutionError(`${label} returned HTTP ${resp.status}: ${summarizeApiError(parsed, resp.statusText)}`);
}
if (typeof parsed === 'string') {
throw new CommandExecutionError(
`${label} returned a non-JSON response`,
'Expected Atlassian REST API JSON. Check the base URL and whether an HTML login, SSO, or proxy page was returned.',
);
}
return parsed;
}
export function queryString(params) {
const qs = new URLSearchParams();
for (const [key, value] of Object.entries(params)) {
if (value === undefined || value === null || value === '') continue;
if (Array.isArray(value)) {
for (const item of value) qs.append(key, String(item));
} else {
qs.set(key, String(value));
}
}
const s = qs.toString();View on GitHub (pinned to 49907e53dc)
Solutions
- Check the base URL — it must be the Atlassian site root (e.g. https://example.atlassian.net) or a reachable REST base, not a login/portal page.
- Re-run with curl to see the actual HTML body and identify who produced it (SSO provider, proxy, captive portal).
- Whitelist the tool in the corporate proxy or run from a network without the intercepting proxy.
- For Data Center, ensure the deployment setting matches the instance so the correct REST path prefix is used.
- If an SSO redirect is unavoidable, use a personal access token / API token so requests authenticate before the SSO page is served.
Example fix
// before (base URL points at a portal that serves HTML 200) ATLASSIAN_BASE_URL=https://intranet.corp.com/confluence-home // after ATLASSIAN_BASE_URL=https://example.atlassian.net
Defensive patterns
Strategy: try-catch
Validate before calling
// preflight: verify the endpoint returns JSON before real work
const res = await fetch(`${baseUrl}/rest/api/space?limit=1`, { headers: authHeaders() });
const ct = res.headers.get('content-type') || '';
if (!ct.includes('application/json')) throw new Error('Endpoint did not return JSON — check base URL/proxy'); Type guard
function isJsonObject(v) { return v !== null && typeof v === 'object' && !Array.isArray(v); } Try / catch
try {
const data = await cmd(args);
} catch (e) {
if (/non-JSON response/.test(e.message)) {
console.error('Got HTML instead of JSON — SSO/proxy intercept or wrong base URL. Inspect with curl.');
} else throw e;
} Prevention
- Always use the site root URL (https://example.atlassian.net), not portal/login pages.
- Test connectivity from the same network the tool runs on (proxies/VPNs differ).
- Use token auth so requests never land on an SSO HTML page.
- Check content-type: application/json in a preflight request.
When it happens
Trigger: The base URL points at a server that returns HTML with status 200 — e.g. an SSO/login redirect, a captive proxy, an expired session page, or a typo'd base URL hitting a website instead of the REST endpoint.
Common situations: Corporate proxy injecting an authentication page; ATLASSIAN_BASE_URL missing the /wiki or /rest path context so a portal page is served; VPN/captive portal returning an HTML block page; pointing cloud credentials at a self-hosted instance whose login screen returns 200 HTML.
Related errors
- ${label} returned malformed JSON: ${err?.message ?? err}
- stack exchange returned malformed JSON: ${error?.message ||
- ${label} returned HTTP ${resp.status}: ${summarizeApiError(p
- ${label} returned an unexpected payload shape; expected an o
- archive snapshots returned malformed JSON: ${error?.message
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/223a17702fc2286c.
Report an issue: GitHub.