{"record":{"id":"e28e2326c0ebf01c","repo":"toeverything/AFFiNE","slug":"invalid-structured-output","errorCode":"invalid_structured_output","errorMessage":"Structured response missing required output_json: ${response.output_text.trim().slice(0, 200)}","messagePattern":"Structured response missing required output_json: (.+?)","errorType":"exception","errorClass":"StructuredResponseParseError","httpStatus":null,"severity":"error","filePath":"packages/backend/server/src/native.ts","lineNumber":875,"sourceCode":"): LlmRerankRequestContract {\n  return llmBuildRerankRequest({\n    model,\n    query: request.query,\n    candidates: request.candidates.map(candidate => ({\n      ...(candidate.id ? { id: candidate.id } : {}),\n      text: candidate.text,\n    })),\n    ...(request.topK ? { topN: request.topK } : {}),\n  });\n}\n\nexport function parseNativeStructuredOutput(\n  response: Pick<LlmStructuredResponse, 'output_text'> & {\n    output_json?: unknown;\n  }\n) {\n  if (response.output_json === undefined) {\n    throw new StructuredResponseParseError(\n      `Structured response missing required output_json: ${response.output_text\n        .trim()\n        .slice(0, 200)}`\n    );\n  }\n\n  return response.output_json;\n}\n\nexport function llmValidateJsonSchema<T = unknown>(\n  schema: Record<string, unknown>,\n  value: T\n): T {\n  if (!nativeLlmModule.llmValidateJsonSchema) {\n    throw new Error('native JSON schema validator is not available');\n  }\n\n  return nativeLlmModule.llmValidateJsonSchema(schema, value) as T;","sourceCodeStart":857,"sourceCodeEnd":893,"githubUrl":"https://github.com/toeverything/AFFiNE/blob/b6de0ad51b76f3daac2d3d6325369ea623ed7ed4/packages/backend/server/src/native.ts#L857-L893","documentation":"parseNativeStructuredOutput() (native.ts:865) asserts that a native LLM structured response carries output_json. When output_json is undefined it throws StructuredResponseParseError, embedding the first 200 characters of output_text as evidence — meaning the model produced only free text and the structured JSON channel the caller requires is missing.","triggerScenarios":"Requesting structured output from the native LLM integration but receiving a response where output_json is undefined (only output_text populated), then passing that response into parseNativeStructuredOutput.","commonSituations":"Provider or model does not support JSON/structured mode; the request was built without the schema/response format so the integration never populated output_json; the model wrapped the JSON in prose or markdown fences; truncated generation; SDK version change altering the structured-output field.","solutions":["Inspect the output_text snippet in the error — if JSON is embedded in prose, tighten the prompt and ensure the request enables the provider's structured/JSON mode so output_json gets populated.","Verify the chosen provider and model support structured output and that the schema is attached to the request.","Guard before parsing: only call parseNativeStructuredOutput when response.output_json !== undefined.","Add a fallback that extracts/repairs JSON from output_text (strip code fences, run a JSON repair pass) when output_json is missing."],"exampleFix":"// before\nconst json = parseNativeStructuredOutput(response); // throws when output_json is undefined\n\n// after\nif (response.output_json === undefined) {\n  throw new Error(\n    `LLM returned unstructured output: ${response.output_text.trim().slice(0, 200)}`\n  );\n}\nconst json = parseNativeStructuredOutput(response);","handlingStrategy":"type-guard","validationCode":"if (response.output_json === undefined) {\n  // do not call parseNativeStructuredOutput; repair or fail explicitly\n  throw new Error(`Unstructured LLM output: ${response.output_text.slice(0, 200)}`);\n}","typeGuard":"function hasStructuredOutput(\n  r: Pick<LlmStructuredResponse, 'output_text'> & { output_json?: unknown }\n): r is typeof r & { output_json: unknown } {\n  return r.output_json !== undefined;\n}","tryCatchPattern":"try {\n  const json = parseNativeStructuredOutput(response);\n} catch (e) {\n  if (e instanceof StructuredResponseParseError) {\n    // inspect e.message snippet, retry with stricter prompt/schema\n  } else throw e;\n}","preventionTips":["Always enable the provider's structured/JSON mode and attach the schema so output_json is populated.","Guard output_json before parsing instead of parsing blindly.","Keep a JSON-repair fallback for models that wrap JSON in prose."],"tags":["llm","structured-output","json","parsing"],"backgroundTag":"llm-invalid-json-output","analyzedSha":"b6de0ad51b76f3daac2d3d6325369ea623ed7ed4","analyzedAt":"2026-08-18T21:16:52.546Z","contentChangedAt":"2026-08-18T21:16:52.546Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}