deepseek-ai/deepseek-harness · error
conversation.serializeDraftImages: one or more draft images
Error message
conversation.serializeDraftImages: one or more draft images are no longer available
What it means
serializeDraftImages() resolves ordered draft ids to base64 wire payloads for slash-command submission (the composer releases images only after the command settles successfully). Like sendSession, any id that no longer lives in draftAttachments throws immediately — the command is never sent with a partial image set.
Source
Thrown at packages/client/ui-conversation/src/client/service.ts:203
const attachments: ComposerAttachment[] = []
for (const id of ids) {
const attachment = this.draftAttachments.get(id)
if (attachment !== undefined) attachments.push(attachment)
}
return attachments
}
/**
* Serialize ordered draft images to command-submit wire payloads without
* sending or releasing them (the composer releases only after the command
* settles successfully).
* @param imageIds - ordered draft-local attachment ids.
* @returns base64 payloads in id order.
*/
async serializeDraftImages(imageIds: readonly DraftAttachmentId[]): Promise<readonly SubmitImageAttachment[]> {
const attachments = this.draftImages(imageIds)
if (attachments.length !== imageIds.length) {
throw new Error('conversation.serializeDraftImages: one or more draft images are no longer available')
}
return Promise.all(attachments.map(attachment => this.encodeImage(attachment.file)))
}
/**
* Release one browser-owned draft image and preview URL.
* @param id - draft attachment id.
*/
releaseDraftImage(id: DraftAttachmentId): void {
const attachment = this.draftAttachments.get(id)
if (attachment === undefined) return
this.draftAttachments.delete(id)
this.createdImageUrls.delete(attachment.previewUrl)
revokePreview(attachment.previewUrl)
}
/**
* Release a set of browser-owned draft images.View on GitHub (pinned to b150a551b8)
Solutions
- Validate id liveness (draftImages length check) and refresh the id list from the composer before serializing
- Retry the command without the released images if the command tolerates an empty image set
- Audit the release policy so images release exactly once, on settle
Defensive patterns
Strategy: validation
Validate before calling
const live = service.draftImages(imageIds)
if (live.length !== imageIds.length) {
throw new Error('image no longer attached; re-attach before submitting')
}
return service.serializeDraftImages(live.map(a => a.id)) Prevention
- Serialize draft images and execute the command inside one attempt so ids cannot go stale between the steps
- Release command images exactly once, on settle
- Mirror releases into UI chip state so the two never drift
When it happens
Trigger: A slash-command submit carrying images where an id was already released: an earlier successful command released its images, the chip was removed mid-flight, or the ids predate a remount of the runtime that owns attachments.
Common situations: Retrying a command whose first run released the images on success; UI chip state drifting from the runtime attachment map after a failed outcome kept the draft.
Related errors
- conversation.sendSession: one or more draft images are no lo
- command directory warmup failed: ${entry.lastError instanceo
- command.list failed: ${result.error.code}: ${result.error.me
- notice.imagesUnsupported
- command.execute failed: ${result.error.code}: ${result.error
AI-assisted analysis of deepseek-ai/deepseek-harness@b150a551b8 (2026-08-24).
Data as JSON: /api/errors/9918831e7635ced1.
Report an issue: GitHub.