{"record":{"id":"3cca3eeffc842f3b","repo":"PaddlePaddle/PaddleOCR","slug":"token-is-required-set-paddleocr-access-token-or-p","errorCode":null,"errorMessage":"Token is required. Set PADDLEOCR_ACCESS_TOKEN or pass token option.","messagePattern":"Token is required\\. Set PADDLEOCR_ACCESS_TOKEN or pass token option\\.","errorType":"exception","errorClass":"AuthError","httpStatus":null,"severity":"error","filePath":"api_sdk/typescript/src/client.ts","lineNumber":38,"sourceCode":"import type { ClientOptions, DocParsingRequest, OCRRequest, SaveResourceOptions } from \"./models.js\";\nimport { isDocumentParsingModel, isOCRModel, Model } from \"./models.js\";\nimport type { BatchStatus, DocParsingResult, Job, JobStatus, OCRResult } from \"./results.js\";\n\nconst DEFAULT_BASE_URL = \"https://paddleocr.aistudio-app.com\";\n\ninterface ResourceSavePlan {\n  resourceUrl: string;\n  filename: string;\n}\n\nexport class PaddleOCRClient {\n  private http: HttpClient;\n  private poller: Poller;\n\n  constructor(options: ClientOptions = {}) {\n    const token = options.token || process.env.PADDLEOCR_ACCESS_TOKEN || \"\";\n    if (!token) {\n      throw new AuthError(\"Token is required. Set PADDLEOCR_ACCESS_TOKEN or pass token option.\");\n    }\n    const baseUrl = options.baseUrl || process.env.PADDLEOCR_BASE_URL || DEFAULT_BASE_URL;\n    const requestTimeout = options.requestTimeout || options.timeout || 300000;\n    const pollTimeout = options.pollTimeout || options.timeout || 600000;\n\n    this.http = new HttpClient(\n      token,\n      baseUrl,\n      requestTimeout,\n      options.fetch,\n      options.clientPlatform,\n    );\n    this.poller = new Poller(this.http, pollTimeout);\n  }\n\n  async ocr(req: OCRRequest, options?: { signal?: AbortSignal }): Promise<OCRResult> {\n    const job = await this.submitOcr(req, options);\n    return this.waitOcrResult(job, options);","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/api_sdk/typescript/src/client.ts#L20-L56","documentation":"Thrown by unwrap_api_response in paddleocr/_api_client/_core.py:170 when a 2xx API response's JSON envelope has no object 'data' field. The PaddleOCR API contract wraps every payload as {code, msg, data}; after the code check passes, 'data' must be a JSON object. A missing, null, list, or scalar 'data' triggers this ResponseFormatError. It signals the server response deviated from the documented schema, not a client input problem.","triggerScenarios":"Any successful call to submit_url/submit_file/get_job_status/get_batch_status where the returned JSON lacks 'data' or has data as a string/list/null — e.g. a proxy or gateway returning {\"code\":0} with no data, or an API version change that renamed the field.","commonSituations":"Hitting a different/older API endpoint than the SDK targets; a corporate proxy or WAF rewriting responses; a service version bump changing the envelope; a maintenance page returning 200 with a JSON body without 'data'.","solutions":["Log the raw response body (catch ResponseFormatError and inspect response text via the SDK's http layer or a manual requests call) to see what the server actually returned","Verify the base URL / API region configured on the client matches the current PaddleOCR API docs","Check for SDK updates — an envelope change on the server usually gets a matching SDK release","If a proxy interferes, bypass it or whitelist the API host","Report the raw payload to PaddleOCR maintainers if the server is genuinely returning an malformed envelope"],"exampleFix":"// before\njob_id = client.submit_file(...)\n\n// after\nfrom paddleocr._api_client.errors import ResponseFormatError\ntry:\n    job_id = client.submit_file(...)\nexcept ResponseFormatError as e:\n    logger.error(\"Unexpected API envelope: %s\", e)\n    raise","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"def is_api_envelope(payload: object) -> bool:\n    return isinstance(payload, dict) and isinstance(payload.get(\"data\"), dict)","tryCatchPattern":"from paddleocr._api_client.errors import ResponseFormatError\ntry:\n    result = client.get_job_status(job_id)\nexcept ResponseFormatError as e:\n    # server broke the envelope contract; capture raw traffic and report\n    logger.error(\"Malformed API envelope: %s\", e)\n    raise","preventionTips":["Pin the SDK version matched to the API version you call","Log raw request/response pairs in staging to catch envelope drift early","Route API traffic outside HTML-rewriting proxies"],"tags":["api","response-format","schema","json"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}