coleam00/Archon · warning

codex.structured_output_not_json

codex.structured_output_not_json

Error message

⚠️ Structured output requested but Codex returned non-JSON text. Downstream $nodeId.output.field references may not evaluate correctly.

What it means

Codex was invoked with structured output requested, but the provider's accumulated response text failed JSON.parse. Since downstream workflow nodes may reference `$nodeId.output.field`, the provider emits a system message warning that those references may not evaluate. It is a degraded-output warning, not a thrown exception.

Source

Thrown at packages/providers/src/codex/provider.ts:800

    if (event.type === 'turn.completed') {
      getLog().debug('turn_completed');
      const usage = extractUsageFromCodexEvent(event as TurnCompletedEvent);

      // Codex returns structured output inline in agent_message text.
      // Normalize: parse as JSON and put on structuredOutput so the
      // dag-executor can handle all providers uniformly.
      let structuredOutput: unknown;
      if (hasOutputFormat && accumulatedText) {
        try {
          structuredOutput = JSON.parse(accumulatedText);
          getLog().debug('codex.structured_output_parsed');
        } catch {
          getLog().warn(
            { outputPreview: accumulatedText.slice(0, 200) },
            'codex.structured_output_not_json'
          );
          yield {
            type: 'system',
            content:
              '⚠️ Structured output requested but Codex returned non-JSON text. ' +
              'Downstream $nodeId.output.field references may not evaluate correctly.',
          };
        }
      }

      yield {
        type: 'result',
        sessionId: resolvedThreadId ?? undefined,
        tokens: usage,
        ...(structuredOutput !== undefined ? { structuredOutput } : {}),
      };
      return;
    }
  }

View on GitHub (pinned to 0773b97458)

Solutions

  1. Re-run the node with an explicit instruction to output only raw JSON with no fences or commentary
  2. Validate/repair the text before relying on it: strip code fences and retry JSON.parse downstream
  3. Use the provider's native structured-output/JSON mode instead of prompt-only requests
  4. Treat the system message as a failure signal and gate downstream $nodeId.output.* references on a schema-validated parse

Example fix

// before: parse accumulated text directly
const data = JSON.parse(accumulatedText);
// after: tolerate fences, validate shape
const raw = accumulatedText.replace(/^```(?:json)?\n?|\n?```$/g, '').trim();
const data = JSON.parse(raw);
if (typeof data !== 'object' || data === null) throw new Error('codex structured output is not an object');
Defensive patterns

Strategy: validation

Validate before calling

function isUsableStructuredOutput(text: string): boolean {
  try {
    const v = JSON.parse(text.replace(/^```(?:json)?\n?|\n?```$/g, '').trim());
    return typeof v === 'object' && v !== null;
  } catch { return false; }
}

Type guard

function isRecord(v: unknown): v is Record<string, unknown> {
  return typeof v === 'object' && v !== null && !Array.isArray(v);
}

Try / catch

let parsed: Record<string, unknown> | null = null;
try {
  parsed = JSON.parse(raw.replace(/^```(?:json)?\n?|\n?```$/g, '').trim());
} catch (e) {
  // fall back: re-run the node or surface a typed failure instead of reading output.field
  parsed = null;
}

Prevention

When it happens

Trigger: streamCodexEvents (called by sendQuery) accumulates Codex text output, tries JSON.parse at the end, and the catch block fires because the model returned prose, markdown fences, or truncated JSON despite the structured-output request.

Common situations: Model ignored the JSON instruction and answered conversationally; response wrapped the JSON in ```json fences or added commentary; long outputs got truncated mid-object; model version change altered formatting behavior.

Related errors


AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01). Data as JSON: /api/errors/d2403e54ccbb22b7. Report an issue: GitHub.