{"record":{"id":"b784de12ef692aac","repo":"PaddlePaddle/PaddleOCR","slug":"response-body-is-missing-data","errorCode":null,"errorMessage":"Response body is missing data.","messagePattern":"Response body is missing data\\.","errorType":"exception","errorClass":"ResponseFormatError","httpStatus":null,"severity":"error","filePath":"api_sdk/typescript/src/internal/http.ts","lineNumber":173,"sourceCode":"  private async fetchJson<T>(\n    url: string,\n    init: RequestInit,\n    signal?: AbortSignal,\n    withAuth: boolean = true,\n    timeoutMs?: number,\n  ): Promise<T> {\n    const resp = await this.fetch(url, init, signal, withAuth, timeoutMs);\n    let payload: APIResponse<T>;\n    try {\n      payload = await resp.json() as APIResponse<T>;\n    } catch (error) {\n      throw new ResponseFormatError(\"Expected a JSON response body.\", { cause: error });\n    }\n    if (payload.code !== undefined && payload.code !== 0) {\n      throw new APIError(resp.status, payload.msg || \"PaddleOCR official API request failed.\");\n    }\n    if (!payload || typeof payload !== \"object\" || !(\"data\" in payload)) {\n      throw new ResponseFormatError(\"Response body is missing data.\");\n    }\n    return payload.data;\n  }\n\n  private async fetch(\n    url: string,\n    init: RequestInit,\n    signal?: AbortSignal,\n    withAuth: boolean = true,\n    timeoutMs?: number,\n  ): Promise<Response> {\n    const headers: Record<string, string> = {\n      ...(init.headers as Record<string, string> || {}),\n    };\n    if (withAuth) {\n      headers.Authorization = `Bearer ${this.token}`;\n      if (this.clientPlatform) {\n        headers[\"Client-Platform\"] = this.clientPlatform;","sourceCodeStart":155,"sourceCodeEnd":191,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/api_sdk/typescript/src/internal/http.ts#L155-L191","documentation":"ResponseFormatError with 'Response body is missing data.' is thrown by fetchJson<T>() when the JSON envelope parsed fine and code was 0/absent, but the top-level `data` field is missing. The SDK's contract requires every successful response to be shaped { code, msg, data }, and it returns payload.data to callers — no data means the contract is broken.","triggerScenarios":"Any JSON API call (submitJson, getJobStatus, getBatchStatus) whose 2xx response body is valid JSON but lacks the data key — e.g. { \"code\": 0, \"msg\": \"ok\" } or a completely unrelated JSON object returned by a misrouted endpoint.","commonSituations":"Pointing the SDK at a stub/mock server that returns simplified JSON without the data envelope; API version mismatch where a newer/older server drops the envelope; load balancer health-check responses; authentication middlewares that short-circuit with { \"msg\": ... } JSON.","solutions":["Confirm the base URL targets the real PaddleOCR API host expected by this SDK version","Capture the raw response with a custom fetchImpl to see exactly which field is missing","Align SDK and server versions — the data envelope is part of the contract; drift on either side produces this","If you run a mock server, make it return the full { code: 0, msg: \"ok\", data: {...} } shape"],"exampleFix":"import { ResponseFormatError } from \"paddleocr-api/errors\";\ntry {\n  const jobs = await client.getBatchStatus(batchId);\n} catch (e) {\n  if (e instanceof ResponseFormatError && e.message.includes(\"missing data\")) {\n    console.error(\"Server broke the response contract:\", e.message);\n  }\n}","handlingStrategy":"try-catch","validationCode":"function hasDataField(v: unknown): v is { data: unknown } {\n  return typeof v === \"object\" && v !== null && \"data\" in v;\n}","typeGuard":"function isApiResponse<T>(v: unknown): v is { code?: number; msg?: string; data: T } {\n  return typeof v === \"object\" && v !== null && \"data\" in v;\n}","tryCatchPattern":"try {\n  const jobs = await poller.getBatchStatus(batchId);\n} catch (e) {\n  if (e instanceof ResponseFormatError && e.message.includes(\"missing data\")) {\n    // contract violation: do not retry blindly; verify endpoint and versions\n    logger.error(\"Response contract broken (no data field)\");\n  }\n  throw e;\n}","preventionTips":["Make mock servers return the full { code, msg, data } envelope","Pin SDK and API versions together in your changelog so drift is deliberate","Add a contract smoke test (submit → status → result) against a staging endpoint"],"tags":["response-format","contract","http","typescript"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}