chatboxai/chatbox · warning · Error
Only failed session attachments can be retried
Error message
Only failed session attachments can be retried
What it means
Thrown by retrySessionAttachment when the attachment exists but its status is not 'failed'. Only failed attachments are eligible for retry; pending/queued/processing/ready/canceled are rejected to avoid conflicting with an in-flight pipeline or resurrecting a clean state.
Source
Thrown at src/main/session-attachment-rag/db.ts:671
export async function markSessionAttachmentFailed(id: number, error: string) {
const client = getDatabase()
const result = await client.execute({
sql: 'UPDATE session_attachment SET status = ?, error = ?, processing_started_at = NULL, completed_at = NULL WHERE id = ? AND status != ?',
args: ['failed', error, id, 'canceled'],
})
if ((result.rowsAffected || 0) > 0) {
log.debug(`${SESSION_ATTACHMENT_RAG_LOG_PREFIX} [DB] Marked attachment failed: attachmentId=${id}, error=${error}`)
}
}
export async function retrySessionAttachment(id: number) {
const client = getDatabase()
const existing = await getSessionAttachment(id)
if (!existing) {
throw new Error(`Session attachment ${id} not found`)
}
if (existing.status !== 'failed') {
throw new Error('Only failed session attachments can be retried')
}
await client.execute({
sql: 'UPDATE session_attachment SET status = ?, indexing_stage = ?, total_chunks = 0, embedded_chunks = 0, error = NULL, processing_started_at = NULL, completed_at = NULL WHERE id = ?',
args: ['pending', 'queued', id],
})
log.debug(`${SESSION_ATTACHMENT_RAG_LOG_PREFIX} [DB] Reset attachment to pending: attachmentId=${id}`)
}
export async function cancelSessionAttachment(id: number) {
const client = getDatabase()
await client.execute({
sql: 'UPDATE session_attachment SET status = ?, error = NULL, processing_started_at = NULL, completed_at = NULL WHERE id = ? AND status IN (?, ?, ?)',
args: ['canceled', id, 'pending', 'indexing', 'failed'],
})
log.debug(`${SESSION_ATTACHMENT_RAG_LOG_PREFIX} [DB] Marked attachment canceled: attachmentId=${id}`)
}
export async function rebindSessionAttachment(id: number, sessionId: string, messageId: string) {View on GitHub (pinned to 81571269ad)
Solutions
- Gate the retry button in the UI on status === 'failed' only.
- If the status changed between render and click, swallow this error and refresh the row from the DB.
- For canceled attachments, offer 're-upload' instead of 'retry' since retry is intentionally blocked.
- Re-read status immediately before calling retry if the list is long-lived.
Example fix
// before
if (existing.status !== 'failed') throw new Error('Only failed session attachments can be retried')
// caller guard
if (attachment.status === 'failed') await retrySessionAttachment(attachment.id) Defensive patterns
Strategy: validation
Validate before calling
const a = await getSessionAttachment(id)
if (!a || a.status !== 'failed') { return } Type guard
function isRetryStatusBlocked(e: unknown): e is Error { return e instanceof Error && e.message === 'Only failed session attachments can be retried' } Try / catch
try { await retrySessionAttachment(id) } catch (e) { if (isRetryStatusBlocked(e)) { ui.refreshRow(id); return } throw e } Prevention
- Show retry only for status==='failed'.
- Re-read status right before retrying in long-lived lists.
- Use re-upload (not retry) for canceled attachments.
When it happens
Trigger: Calling retry on an attachment currently in 'processing' or 'queued', or one already 'ready'/'canceled'. The check is strict equality status !== 'failed'.
Common situations: UI shows a retry button for all rows regardless of status; double-click retry on a row that just transitioned from failed to pending; retrying a canceled attachment (cancellation is terminal by intent).
Related errors
- Session attachment ${id} not found
- Failed to mark attachment ${attachment.id} ready
- Attachment content not found or empty
- Attachment did not produce any retrievable chunks
- Invalid rerank model format: ${modelString}
AI-assisted analysis of chatboxai/chatbox@81571269ad (2026-08-12).
Data as JSON: /api/errors/3d265cfdf54d582f.
Report an issue: GitHub.