openai/codex · error · QueueServiceError
queue storage failed: {0}
Error message
queue storage failed: {0} What it means
Wraps ThreadStoreError via #[from] (codex-rs/ext/queue/src/service.rs:48-49) and is returned by every QueuedItemService method that touches the underlying QueueStore: enqueue, list/list_page, update, delete, reorder, and start. The local store is SQLite-backed and converts storage-layer failures into ThreadStoreError::Internal (queue_store.rs:78-81). start() also fabricates ThreadStoreError::InvalidRequest ('queue is empty' / 'queued submission not found: {id}') when the requested item is missing (service.rs:380-385), and reorder() returns InvalidRequest when the ids are not an exact permutation of the queue.
Source
Thrown at codex-rs/ext/queue/src/service.rs:48
use codex_thread_store::QueueStore;
use codex_thread_store::QueuedUserSubmissionRecord;
use codex_thread_store::ThreadStoreError;
use thiserror::Error;
use tokio::sync::Mutex;
use tokio::sync::OwnedMutexGuard;
use tokio::sync::broadcast::error::TryRecvError;
use uuid::Uuid;
/// One user message waiting to start on its thread.
#[derive(Clone, Debug, PartialEq)]
pub struct QueuedItem {
pub id: String,
pub input: TurnInput,
}
#[derive(Debug, Error)]
pub enum QueueServiceError {
#[error("queue storage failed: {0}")]
Storage(#[from] ThreadStoreError),
#[error("queued submission payload is invalid: {0}")]
InvalidPayload(#[from] serde_json::Error),
#[error("local queued attachment is invalid: {0}")]
InvalidAttachment(#[from] std::io::Error),
#[error("Core failed to submit queued user message: {0}")]
CoreSubmissionError(#[from] CodexErr),
#[error("only user input can be added to the user-message queue")]
InvalidInput,
#[error(
"queued user input exceeds the maximum length of {MAX_USER_INPUT_TEXT_CHARS} characters ({actual_chars} provided)"
)]
InputTooLarge { actual_chars: usize },
}
#[derive(Clone)]
pub struct QueuedItemService {
queue: Arc<dyn QueueStore>,View on GitHub (pinned to 339751715c)
Solutions
- Read the inner ThreadStoreError: InvalidRequest means bad request data (fix the ids), Internal usually means SQLite-level trouble.
- For 'queued submission not found' or an empty queue, re-fetch with list(thread_id) and act on current ids.
- For reorder, pass exactly the ids returned by list(), each exactly once, in the new order.
- For Internal SQLite errors, check the state database's permissions, concurrent holders, and disk space.
Example fix
// before service.reorder(thread_id, vec![first_id]).await?; // partial list => InvalidRequest // after - ids must be the complete queue, each once, in the new order let ids: Vec<String> = desired_order.into_iter().map(|item| item.id).collect(); service.reorder(thread_id, ids).await?;
Defensive patterns
Strategy: try-catch
Validate before calling
// Rust - verify a reorder payload is a permutation of the live queue before calling reorder
let current: std::collections::HashSet<String> =
service.list(thread_id).await?.into_iter().map(|i| i.id).collect();
let next: std::collections::HashSet<String> = new_order.iter().cloned().collect();
debug_assert_eq!(current, next); // caller guarantee: every id, exactly once
service.reorder(thread_id, new_order).await Try / catch
match service.start(thread, Some(id), None).await {
Ok(submission) => { /* ... */ }
Err(QueueServiceError::Storage(ThreadStoreError::InvalidRequest { message }))
if message.contains("not found") || message.contains("empty") =>
{
// stale snapshot: refresh with list() and pick a current id
}
Err(QueueServiceError::Storage(ThreadStoreError::Internal { message })) => {
// SQLite-level failure: check db locks, permissions, disk space
}
Err(e) => return Err(e),
} Prevention
- Re-fetch the queue with list() before acting on ids captured earlier.
- reorder() takes the complete id set exactly once; derive it from list().
- Avoid concurrent writers on one state database; SQLite lock errors surface as Internal.
- Handle InvalidRequest separately from Internal - only the first is a caller bug.
When it happens
Trigger: Any queue operation hitting a SQLite error (locked database, corrupt file, disk full); reorder() with an id list that omits or duplicates queue items; start(thread, Some(id)) where the item was already dequeued by another client.
Common situations: Two processes sharing one state database (lock contention); a UI acting on a stale queue snapshot after another client consumed an item; drag-and-drop reorder that dropped an item from the list.
Related errors
- queued submission payload is invalid: {0}
- local queued attachment is invalid: {0}
- pid-managed app-server shutdown is unsupported on this platf
- pid-managed updater shutdown is unsupported on this platform
- failed to read start time for pid-managed app server {pid}
AI-assisted analysis of openai/codex@339751715c (2026-08-25).
Data as JSON: /api/errors/a2f0c89cf67621eb.
Report an issue: GitHub.