openai/codex · warning · LunaSamplerError

Luna response did not contain assistant output

Error message

Luna response did not contain assistant output

What it means

The Luna response reached Completed but accumulated neither an assistant OutputText item nor any output_text deltas — there is no text to classify. A model-behavior anomaly (empty completion), classified non-retryable by the sampler, so callers should degrade rather than loop.

Source

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

    pub reasoning_effort: ReasoningEffort,
    /// Owning turn identifier used for request attribution.
    pub turn_id: String,
}

/// 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 {

View on GitHub (pinned to 339751715c)

Solutions

  1. Treat as 'no classification' and proceed unclassified — guardian degrades gracefully.
  2. Retry the turn once at the caller level; empties are often transient.
  3. If reproducible, loosen the strict output schema slightly (optional fields) and re-test.
  4. Capture raw ResponseEvents to confirm what the model actually emitted.
Defensive patterns

Strategy: fallback

Try / catch

match sampler.sample(request).await {
    Err(LunaSamplerError::MissingOutput) => {
        tracing::warn!("luna returned no output; proceeding unclassified");
        Classification::none()
    }
    r => r?,
}

Prevention

When it happens

Trigger: LunaSampler::sample receives a Completed event with zero assistant text: the model returned empty content under the strict JSON schema, or events carried only reasoning/metadata items.

Common situations: Output schema too restrictive causing empty completions; responses-lite/WebSocket beta behaving differently for tool-less structured requests; transient model glitch.

Related errors


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