{"record":{"id":"8420383eb67bf117","repo":"CherryHQ/cherry-studio","slug":"invalid-json-from-feishu-registration-api-text","errorCode":null,"errorMessage":"Invalid JSON from Feishu registration API: ${text.slice(0, 200)}","messagePattern":"Invalid JSON from Feishu registration API: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/main/ai/channels/adapters/feishu/FeishuAppRegistration.ts","lineNumber":51,"sourceCode":"\ntype PollStatus = 'authorization_pending' | 'slow_down' | 'access_denied' | 'expired_token'\n\nasync function postRegistration(baseUrl: string, params: Record<string, string>): Promise<Record<string, unknown>> {\n  const url = `${baseUrl}/oauth/v1/app/registration`\n  // The Feishu registration API requires application/x-www-form-urlencoded,\n  // matching the format used by @larksuiteoapi/openclaw-lark-tools.\n  const body = new URLSearchParams(params).toString()\n  const res = await net.fetch(url, {\n    method: 'POST',\n    headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\n    body\n  })\n\n  const text = await res.text()\n  try {\n    return JSON.parse(text) as Record<string, unknown>\n  } catch {\n    throw new Error(`Invalid JSON from Feishu registration API: ${text.slice(0, 200)}`)\n  }\n}\n\nexport async function registrationBegin(domain: FeishuDomain): Promise<RegistrationBeginResult> {\n  const baseUrl = BASE_URLS[domain]\n\n  // Step 1: init — check supported auth methods\n  const initRes = await postRegistration(baseUrl, { action: 'init' })\n  logger.info('Feishu registration init response', { supported: initRes })\n\n  // Step 2: begin — start device flow\n  const res = await postRegistration(baseUrl, {\n    action: 'begin',\n    archetype: 'PersonalAgent',\n    auth_method: 'client_secret',\n    request_user_info: 'open_id'\n  })\n","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/CherryHQ/cherry-studio/blob/726446b54cd69ffe51a276638672f6d95ca0768c/src/main/ai/channels/adapters/feishu/FeishuAppRegistration.ts#L33-L69","documentation":"Thrown by postRegistration() in FeishuAppRegistration when the registration endpoint returns a body that JSON.parse cannot parse. The message includes the first 200 chars of the raw text for diagnosis. postRegistration POSTs URL-encoded params to the registration base URL.","triggerScenarios":"net.fetch to the registration URL succeeds (res completes) but res.text() is HTML (error page), plaintext, or empty, so JSON.parse throws.","commonSituations":"Corporate/MITM proxy returning an HTML block page, wrong BASE_URLS[domain] hitting a non-API host, Feishu maintenance page, or a redirect to a login HTML page.","solutions":["Inspect the first 200 chars in the message — HTML typically indicates a proxy/captive portal or wrong host.","Verify BASE_URLS for the chosen FeishuDomain (feishu/lark) point at the live registration API host.","Ensure outbound network from the host allows the registration endpoint without HTML interception.","If text is empty, treat as a transient server fault and retry the registration call."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Sanity-check the registration endpoint reachability before the flow.\nasync function registrationEndpointHealthy(domain: FeishuDomain): Promise<boolean> {\n  try {\n    const res = await net.fetch(BASE_URLS[domain], { method: 'POST', body: new URLSearchParams({ action: 'init' }) })\n    const text = await res.text()\n    return text.trim().startsWith('{')\n  } catch { return false }\n}","typeGuard":"function isFeishuRegistrationJsonError(e: unknown): e is Error {\n  return e instanceof Error && e.message.startsWith('Invalid JSON from Feishu registration API:')\n}","tryCatchPattern":"try {\n  await registrationBegin(domain)\n} catch (e) {\n  if (isFeishuRegistrationJsonError(e)) {\n    notifyUser('Feishu registration endpoint unreachable (proxy/maintenance?)')\n    return\n  }\n  throw e\n}","preventionTips":["Ensure no HTML-intercepting proxy sits between the host and Feishu's registration API.","Verify BASE_URLS for the chosen domain point at the live API host.","Treat HTML bodies as a network-layer problem, not a credentials problem."],"tags":["feishu","registration","json-parse","network","proxy"],"backgroundTag":null,"analyzedSha":"726446b54cd69ffe51a276638672f6d95ca0768c","analyzedAt":"2026-08-12T17:30:37.448Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}