{"record":{"id":"0354ec41372cdbd7","repo":"firecrawl/firecrawl","slug":"product-extraction-failed-service-returned-an-une","errorCode":null,"errorMessage":"Product extraction failed: service returned an unexpected response shape (missing 'product')","messagePattern":"Product extraction failed: service returned an unexpected response shape \\(missing 'product'\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"apps/api/src/scraper/scrapeURL/transformers/product.ts","lineNumber":64,"sourceCode":"      .catch(() => ({ detail: \"Unknown error\" }));\n    throw new Error(`Product extraction failed: ${error.detail}`);\n  }\n\n  let data: any;\n  try {\n    data = await response.json();\n  } catch {\n    throw new Error(\n      \"Product extraction failed: service returned a non-JSON response\",\n    );\n  }\n\n  // The service contract is a 200 with a body of `{ product: Product | null }`.\n  // A body that isn't an object, or is missing the `product` key entirely, is a\n  // malformed response -- surface it as a service failure rather than silently\n  // reporting \"no product found\" (which is reserved for an explicit `null`).\n  if (typeof data !== \"object\" || data === null || !(\"product\" in data)) {\n    throw new Error(\n      \"Product extraction failed: service returned an unexpected response shape (missing 'product')\",\n    );\n  }\n\n  if (data.product) {\n    document.product = data.product;\n  } else {\n    // `product` is null: the page loaded but is not a product page.\n    document.warning =\n      \"No product found on this page; it does not appear to be a product page.\" +\n      (document.warning ? \" \" + document.warning : \"\");\n  }\n  return document;\n}\n","sourceCodeStart":46,"sourceCodeEnd":79,"githubUrl":"https://github.com/firecrawl/firecrawl/blob/656bffcc2883f1af5befe38766b1ff5f0469993a/apps/api/src/scraper/scrapeURL/transformers/product.ts#L46-L79","documentation":"The service returned valid JSON with HTTP 2xx, but the body is not an object or is missing the `product` key. The contract is `{ product: Product | null }`; an object without `product` is a malformed response surfaced as a failure rather than silently reported as \"no product found\" (which is reserved for an explicit null).","triggerScenarios":"typeof data !== 'object', data === null, or !('product' in data) at product.ts:63. The service returned e.g. {} or { error: '...' } or an array.","commonSituations":"Version skew between the API and the extraction service (new response schema); service returns an error object with a 200 status; service returns a top-level array instead of an object.","solutions":["Inspect the actual JSON body the service returns for this input.","Align the service to return { product: Product | null }.","Pin or coordinate the service version with the API deployment.","Add a contract test covering the response shape."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"// If you control the fetch, narrow the body before using it:\nfunction isProductEnvelope(data: unknown): data is { product: unknown } {\n  return typeof data === 'object' && data !== null && 'product' in data;\n}","tryCatchPattern":"try {\n  await fetchProduct(meta, document);\n} catch (e) {\n  if (e.message.includes('unexpected response shape')) {\n    meta.logger.error('Product service schema drift', { error: e.message });\n  }\n  throw e;\n}","preventionTips":["Add an integration test asserting the { product: Product | null } envelope.","Version the service API and coordinate schema changes with the API team."],"tags":["product-extraction","microservice","schema","contract-violation"],"analyzedSha":"656bffcc2883f1af5befe38766b1ff5f0469993a","analyzedAt":"2026-08-12T01:18:00.488Z","schemaVersion":2},"datasetVersion":"2026-08-12T06:17:24.410Z"}