toeverything/AFFiNE · error · CopilotPromptInvalid

copilot_prompt_invalid

copilot_prompt_invalid

Error message

Structured response is missing output_json

What it means

capability-runtime's structured generation expects the model response to carry output_json; when it is undefined it throws CopilotPromptInvalid (code `copilot_prompt_invalid`, status `invalid_input`) 'Structured response is missing output_json'. The call executed, but the response did not honor the structured-output contract (often only output_text came back).

Source

Thrown at packages/backend/server/src/plugins/copilot/runtime/capability-runtime.ts:319

    slot = 'prompt.structured'
  ) {
    const contract = requireStructuredOutputContract(responseContract);
    if (!contract) {
      throw new CopilotPromptInvalid('Structured schema contract is required');
    }
    const { request } = await buildCanonicalNativeStructuredRequest({
      model: 'route-selected',
      messages,
      options,
      responseContract: contract,
      attachmentCapability,
    });
    const result = (await this.execute(slot, request, cond, options)) as {
      output_json?: unknown;
      output_text: string;
    };
    if (result.output_json === undefined) {
      throw new CopilotPromptInvalid(
        'Structured response is missing output_json'
      );
    }
    return JSON.stringify(
      llmValidateJsonSchema(request.schema, result.output_json)
    );
  }

  async generateStructuredValue(
    cond: ModelConditions,
    messages: PromptMessage[],
    options: CopilotStructuredOptions,
    responseContract?: RequiredStructuredOutputContract,
    filter?: ProviderFilter,
    slot = 'prompt.structured'
  ) {
    const contract = requireStructuredOutputContract(responseContract);
    if (!contract) {

View on GitHub (pinned to b4c8548c09)

Solutions

  1. Use a model/route that supports native structured output (JSON mode / response contracts)
  2. Verify the responseContract survived request building (not stripped by options overrides or a gateway)
  3. Retry — some providers intermittently omit JSON while succeeding otherwise
  4. Simplify the JSON schema (fewer required fields, less nesting) so the model can satisfy it
Defensive patterns

Strategy: retry

Validate before calling

// guard: only request structured output from models that support it
if (!modelSupportsJsonMode(step.modelId)) {
  throw new Error('model lacks structured-output support — pick a JSON-capable route');
}

Type guard

function isPromptInvalid(e: unknown): boolean {
  return (e as { extensions?: { code?: string } })?.extensions?.code === 'copilot_prompt_invalid';
}

Try / catch

try {
  return await generateStructured(contract, messages, options);
} catch (e) {
  if (isPromptInvalid(e) && /output_json/.test((e as Error).message)) {
    await sleep(500);
    return generateStructured(simplifySchema(contract), messages, options); // retry, simpler schema
  }
  throw e;
}

Prevention

When it happens

Trigger: The chosen model/route ignores or does not support the responseContract (JSON/structured output) built by buildCanonicalNativeStructuredRequest; the provider returned text only; a degraded path dropped the contract; complex schemas make the model fall back to prose.

Common situations: Pointing structured prompts at a model without native JSON mode; provider API changes dropping response_format; overly nested/strict JSON schemas that models fail and answer in text; self-hosted gateways that strip response options.

Related errors


AI-assisted analysis of toeverything/AFFiNE@b4c8548c09 (2026-08-18). Data as JSON: /api/errors/b172ca070e8c420c. Report an issue: GitHub.