openai/codex · warning · LunaSamplerError

Luna response exceeded the output limit

Error message

Luna response exceeded the output limit

What it means

Accumulated output or delta text exceeded MAX_OUTPUT_BYTES (8 KiB) mid-stream and the request aborted. The classifier is intentionally bounded because it must return a small JSON verdict. Non-retryable by design (retry_after_failure returns false for it).

Source

Thrown at codex-rs/ext/guardian-v2/src/async_scorer/sampler.rs:122

}

/// Failures returned while connecting or sampling the Luna model.
#[derive(Debug, Error)]
pub enum LunaSamplerError {
    /// The thread's provider or scoped credentials could not be resolved.
    #[error("could not resolve the Luna model provider: {0}")]
    Provider(#[source] CodexErr),
    /// The Responses WebSocket could not be opened or streamed.
    #[error("Luna Responses WebSocket failed: {0}")]
    Api(#[source] ApiError),
    /// The provider's WebSocket connect deadline elapsed.
    #[error("Luna Responses WebSocket connection timed out")]
    ConnectionTimeout,
    /// The response did not contain an assistant text value.
    #[error("Luna response did not contain assistant output")]
    MissingOutput,
    /// The response exceeded the bounded output limit.
    #[error("Luna response exceeded the output limit")]
    OutputTooLarge,
    /// A newer classification replaced this request when the pool was full.
    #[error("Luna request was superseded by a newer classification")]
    Superseded,
}

struct PooledConnection {
    connection: ResponsesWebsocketConnection,
    // The bridge routes by thread ID, so each socket needs its own identity.
    thread_id: String,
    expires_at: Instant,
    auth_changes: Option<tokio::sync::watch::Receiver<u64>>,
}

struct ConnectionLease {
    connection: PooledConnection,
    idle_connections: Arc<Mutex<Vec<PooledConnection>>>,
    _permit: OwnedSemaphorePermit,

View on GitHub (pinned to 339751715c)

Solutions

  1. Tighten output_schema: bound every string (maxLength) and keep the verdict enum-only.
  2. Keep large evidence in the input; restrict output to labels and scores.
  3. Handle the error as 'no classification' rather than retrying — the sampler will not retry it.
  4. Verify strict schema mode is actually applied to the request.
Defensive patterns

Strategy: fallback

Try / catch

match sampler.sample(request).await {
    Err(LunaSamplerError::OutputTooLarge) => Classification::none(), // never retry
    r => r?,
}

Prevention

When it happens

Trigger: LunaSampler::sample where the model emits prose or a huge JSON object instead of a compact classification matching output_schema.

Common situations: Output schema with unbounded string fields (free-text rationale with no maxLength); model rambling instead of conforming to the strict schema.

Related errors


AI-assisted analysis of openai/codex@339751715c (2026-08-25). Data as JSON: /api/errors/117740c98d22d812. Report an issue: GitHub.