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
- Treat as 'no classification' and proceed unclassified — guardian degrades gracefully.
- Retry the turn once at the caller level; empties are often transient.
- If reproducible, loosen the strict output schema slightly (optional fields) and re-test.
- 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
- Degrade to unclassified instead of surfacing the error to the user.
- Allow at most one caller-level retry; empties are usually transient.
- When reproducible, capture raw ResponseEvents to inspect what the model emitted.
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
- could not resolve the Luna model provider: {0}
- Luna Responses WebSocket failed: {0}
- Luna response exceeded the output limit
- pid-managed app-server shutdown is unsupported on this platf
- pid-managed updater shutdown is unsupported on this platform
AI-assisted analysis of openai/codex@339751715c (2026-08-25).
Data as JSON: /api/errors/3db643e1bd9e8568.
Report an issue: GitHub.