{"record":{"id":"223a17702fc2286c","repo":"jackwener/OpenCLI","slug":"label-returned-a-non-json-response","errorCode":null,"errorMessage":"${label} returned a non-JSON response","messagePattern":"(.+?) returned a non-JSON response","errorType":"http","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/_atlassian/shared.js","lineNumber":218,"sourceCode":"        );\n    }\n    if (resp.status === 404) {\n        throw new EmptyResultError(label, `Atlassian returned 404 for ${url}.`);\n    }\n    if (resp.status === 409) {\n        throw new CommandExecutionError(\n            `${label} returned HTTP 409: ${summarizeApiError(parsed, 'version conflict')}`,\n            'Reload the current Confluence page version and retry the update.',\n        );\n    }\n    if (resp.status === 429) {\n        throw new CommandExecutionError(`${label} returned HTTP 429 (rate limited)`, 'Wait and retry with a smaller limit.');\n    }\n    if (!resp.ok) {\n        throw new CommandExecutionError(`${label} returned HTTP ${resp.status}: ${summarizeApiError(parsed, resp.statusText)}`);\n    }\n    if (typeof parsed === 'string') {\n        throw new CommandExecutionError(\n            `${label} returned a non-JSON response`,\n            'Expected Atlassian REST API JSON. Check the base URL and whether an HTML login, SSO, or proxy page was returned.',\n        );\n    }\n    return parsed;\n}\n\nexport function queryString(params) {\n    const qs = new URLSearchParams();\n    for (const [key, value] of Object.entries(params)) {\n        if (value === undefined || value === null || value === '') continue;\n        if (Array.isArray(value)) {\n            for (const item of value) qs.append(key, String(item));\n        } else {\n            qs.set(key, String(value));\n        }\n    }\n    const s = qs.toString();","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/_atlassian/shared.js#L200-L236","documentation":"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).","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before (base URL points at a portal that serves HTML 200)\nATLASSIAN_BASE_URL=https://intranet.corp.com/confluence-home\n// after\nATLASSIAN_BASE_URL=https://example.atlassian.net","handlingStrategy":"try-catch","validationCode":"// preflight: verify the endpoint returns JSON before real work\nconst res = await fetch(`${baseUrl}/rest/api/space?limit=1`, { headers: authHeaders() });\nconst ct = res.headers.get('content-type') || '';\nif (!ct.includes('application/json')) throw new Error('Endpoint did not return JSON — check base URL/proxy');","typeGuard":"function isJsonObject(v) { return v !== null && typeof v === 'object' && !Array.isArray(v); }","tryCatchPattern":"try {\n  const data = await cmd(args);\n} catch (e) {\n  if (/non-JSON response/.test(e.message)) {\n    console.error('Got HTML instead of JSON — SSO/proxy intercept or wrong base URL. Inspect with curl.');\n  } else throw e;\n}","preventionTips":["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."],"tags":["http","json","html-response","atlassian","proxy"],"backgroundTag":"non-json-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}