{"record":{"id":"d7ec7e7429d95647","repo":"jackwener/OpenCLI","slug":"hf-spaces-returned-malformed-json-err-message","errorCode":null,"errorMessage":"hf spaces returned malformed JSON: ${err?.message ?? err}","messagePattern":"hf spaces returned malformed JSON: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/hf/spaces.js","lineNumber":78,"sourceCode":"        }\n        catch (err) {\n            throw new CommandExecutionError(`hf spaces request failed: ${err?.message ?? err}`);\n        }\n        if (resp.status === 429) {\n            throw new CommandExecutionError(\n                'hf spaces returned HTTP 429 (rate limited)',\n                'Hugging Face throttles unauthenticated traffic; wait a few seconds and retry.',\n            );\n        }\n        if (!resp.ok) {\n            throw new CommandExecutionError(`hf spaces failed: HTTP ${resp.status}`);\n        }\n        let data;\n        try {\n            data = await resp.json();\n        }\n        catch (err) {\n            throw new CommandExecutionError(`hf spaces returned malformed JSON: ${err?.message ?? err}`);\n        }\n        const list = Array.isArray(data) ? data : [];\n        if (!list.length) {\n            throw new EmptyResultError('hf spaces', 'No matching spaces on huggingface.co.');\n        }\n        return list.slice(0, limit).map((s, i) => {\n            const id = String(s.id ?? s._id ?? '');\n            const slash = id.indexOf('/');\n            const author = String(s.author ?? (slash > 0 ? id.slice(0, slash) : ''));\n            const tags = Array.isArray(s.tags) ? s.tags.filter((t) => !String(t).startsWith('license:')).slice(0, 10).join(', ') : '';\n            return {\n                rank: i + 1,\n                id,\n                author,\n                sdk: String(s.sdk ?? ''),\n                likes: s.likes != null ? Number(s.likes) : null,\n                tags,\n                lastModified: String(s.lastModified ?? '').slice(0, 10),","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/hf/spaces.js#L60-L96","documentation":"The response body from the Hugging Face Spaces API could not be parsed as JSON. The library assumes the endpoint returns a JSON array of spaces, so resp.json() throwing is wrapped in a CommandExecutionError with the parse failure message.","triggerScenarios":"resp.json() throws: the server returned HTML (error/login page), an empty body with a 2xx status, truncated responses, or a proxy's plain-text error page instead of JSON.","commonSituations":"Captive portals or proxies intercepting HTTPS and returning HTML; HF returning 200 with an empty body during partial incidents; middleware rewriting responses.","solutions":["Log resp.headers.get('content-type') and the raw body to see what was actually returned","Verify the request reaches the real HF API (no proxy interference) with curl","Retry; if consistent, check HF status page for API incidents","Use Accept: application/json header (already sent) and confirm no middleware alters the response"],"exampleFix":"// before\ndata = await resp.json();\n// after\nconst text = await resp.text();\ntry {\n  data = JSON.parse(text);\n} catch {\n  throw new CommandExecutionError(`hf spaces returned malformed JSON: ${text.slice(0, 120)}`);\n}","handlingStrategy":"type-guard","validationCode":"// pre-flight content-type check on a probe request\nconst head = await fetch('https://huggingface.co/api/spaces?limit=1');\nif (!(head.headers.get('content-type') || '').includes('application/json')) {\n  console.warn('HF response is not JSON — check proxy/interception');\n}","typeGuard":"function isJsonResponse(resp) {\n  return (resp.headers.get('content-type') || '').includes('application/json');\n}","tryCatchPattern":"try {\n  await hfSpaces(query);\n} catch (e) {\n  if (String(e.message).includes('malformed JSON')) {\n    // inspect raw payload / retry once — often transient proxy corruption\n    return await withRetry(() => hfSpaces(query), 1);\n  }\n  throw e;\n}","preventionTips":["Watch for captive portals/intercepting proxies returning HTML","Always send Accept: application/json","Log content-type and first bytes of unexpected bodies","Retry once — corrupted responses are often transient"],"tags":["json","parsing","huggingface","http"],"backgroundTag":"malformed-json-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}